13#include "crypto/cose.h"
35#include <merklecpp/merklecpp.h>
47#ifdef OVERRIDE_MAX_HISTORY_LEN
53 static std::ostream& operator<<(std::ostream& os,
HashOp flag)
100 sig.template wo<ccf::Signatures>(ccf::Tables::SIGNATURES);
101 auto* cose_signatures =
102 sig.template wo<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
104 auto* serialised_tree = sig.template wo<ccf::SerialisedMerkleTree>(
105 ccf::Tables::SERIALISED_MERKLE_TREE);
107 signatures->put(sig_value);
109 serialised_tree->put({});
110 return sig.commit_reserved();
131 void append(
const std::vector<uint8_t>& )
override
138 std::optional<ccf::kv::Term> =
139 std::nullopt)
override
165 const std::vector<uint8_t>& )
override
178 LOG_DEBUG_FMT(
"Issuing signature at {}.{}", txid.view, txid.seqno);
180 txid, std::make_unique<NullTxHistoryPendingTx>(txid, store,
id),
true);
188 std::shared_ptr<ccf::crypto::ECKeyPair_OpenSSL> service_kp_,
191 std::ignore = service_kp_;
196 throw std::logic_error(
"Unimplemented");
204 std::tuple<ccf::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
233 static constexpr size_t sha256_byte_size = 32;
234 static inline void sha256_history(
235 const merkle::HashT<sha256_byte_size>& l,
236 const merkle::HashT<sha256_byte_size>& r,
237 merkle::HashT<sha256_byte_size>& out)
240 uint8_t block[sha256_byte_size * 2];
241 memcpy(&block[0], l.bytes, sha256_byte_size);
242 memcpy(&block[sha256_byte_size], r.bytes, sha256_byte_size);
244 ccf::crypto::openssl_sha256(block, out.bytes);
247 using HistoryTree = merkle::TreeT<sha256_byte_size, ccf::sha256_history>;
252 HistoryTree::Hash root;
253 std::shared_ptr<HistoryTree::Path> path =
nullptr;
258 Proof(
const std::vector<uint8_t>& v)
261 root.deserialise(v, position);
262 path = std::make_shared<HistoryTree::Path>(v, position);
265 [[nodiscard]]
const HistoryTree::Hash&
get_root()
const
277 path(tree->path(index))
284 if (path->max_index() > tree->max_index())
289 if (tree->max_index() == path->max_index())
291 return tree->root() == root && path->verify(root);
294 auto past_root = tree->past_root(path->max_index());
295 return path->verify(*past_root);
298 [[nodiscard]] std::vector<uint8_t>
to_v()
const
300 std::vector<uint8_t> v;
319 std::unordered_map<std::string, CoseKey>& cose_key_cache;
332 std::unordered_map<std::string, CoseKey>& cose_key_cache_) :
338 service_kp(service_kp_),
339 endorsed_cert(endorsed_cert_),
340 cose_signatures_config(cose_signatures_config_),
341 ledger_sign_mode(ledger_sign_mode_),
342 cose_key_cache(cose_key_cache_)
350 std::vector<uint8_t> root_hash{
351 root.
h.data(), root.
h.data() + root.
h.size()};
356 sig.template wo<ccf::Signatures>(ccf::Tables::SIGNATURES);
358 node_kp.
sign_hash(root_hash.data(), root_hash.size());
369 signatures->put(sig_value);
372 auto* cose_signatures =
373 sig.template wo<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
376 const auto tx_id = txid.
to_str();
378 const auto time_since_epoch =
379 std::chrono::duration_cast<std::chrono::seconds>(
380 std::chrono::system_clock::now().time_since_epoch())
383 auto it = cose_key_cache.find(kid);
384 if (it == cose_key_cache.end())
389 CoseKey::from_private(key_der.data(), key_der.size(), key_err);
390 if (!cose_key.is_set())
392 throw std::runtime_error(fmt::format(
393 "cose_key_from_der_private failed: {}",
394 key_err.is_set() ? key_err.to_string() :
"unknown error"));
396 auto [inserted, _] = cose_key_cache.emplace(kid, std::move(cose_key));
404 reinterpret_cast<const uint8_t*
>(kid.data()),
407 reinterpret_cast<const uint8_t*
>(cose_signatures_config.
issuer.data()),
408 cose_signatures_config.
issuer.size(),
409 reinterpret_cast<const uint8_t*
>(cose_signatures_config.
subject.data()),
410 cose_signatures_config.
subject.size(),
411 reinterpret_cast<const uint8_t*
>(tx_id.data()),
417 if (rc != 0 || !cose_buf.is_set())
419 throw std::runtime_error(fmt::format(
420 "cose_sign_ledger failed: {}",
421 cose_err.is_set() ? cose_err.to_string() :
"unknown error"));
423 std::vector<uint8_t> cose_sign(cose_buf.to_vector());
425 cose_signatures->put(cose_sign);
427 auto* serialised_tree = sig.template wo<ccf::SerialisedMerkleTree>(
428 ccf::Tables::SERIALISED_MERKLE_TREE);
431 return sig.commit_reserved();
437 std::unique_ptr<HistoryTree> tree;
454 tree = std::make_unique<HistoryTree>(serialised);
459 tree->insert(merkle::Hash(hash.
h));
464 const merkle::Hash& root = tree->root();
466 std::copy(root.bytes, root.bytes + root.size(), result.
h.begin());
475 tree = std::make_unique<HistoryTree>(merkle::Hash(root.
h));
483 tree->flush_to(index);
489 tree->retract_to(index);
496 throw std::logic_error(fmt::format(
497 "Cannot produce proof for {}: index is older than first index {}, "
498 "and has been flushed from memory",
504 throw std::logic_error(fmt::format(
505 "Cannot produce proof for {}: index is later than last index {}",
509 return {tree.get(), index};
514 return r.
verify(tree.get());
519 LOG_TRACE_FMT(
"mt_serialize_size {}", tree->serialised_size());
520 std::vector<uint8_t> output;
521 tree->serialise(output);
528 "mt_serialize_size ({},{}) {}",
531 tree->serialised_size(from, to));
532 std::vector<uint8_t> output;
533 tree->serialise(from, to, output);
539 return tree->min_index();
544 return tree->max_index();
554 const merkle::Hash& leaf = tree->leaf(index);
556 std::copy(leaf.bytes, leaf.bytes + leaf.size(), result.
h.begin());
566 T replicated_state_tree;
573 size_t sig_tx_interval;
574 size_t sig_ms_interval;
580 std::optional<ccf::crypto::Pem> endorsed_cert = std::nullopt;
582 struct ServiceSigningIdentity
584 const std::shared_ptr<ccf::crypto::ECKeyPair_OpenSSL> service_kp;
589 std::optional<ServiceSigningIdentity> signing_identity = std::nullopt;
591 std::unordered_map<std::string, CoseKey> cose_key_cache;
598 size_t sig_tx_interval_ = 0,
599 size_t sig_ms_interval_ = 0,
600 bool signature_timer =
false) :
604 sig_tx_interval(sig_tx_interval_),
605 sig_ms_interval(sig_ms_interval_)
614 std::shared_ptr<ccf::crypto::ECKeyPair_OpenSSL> service_kp_,
617 if (signing_identity.has_value())
619 throw std::logic_error(
620 "Called set_service_signing_identity() multiple times");
625 signing_identity.emplace(ServiceSigningIdentity{
626 service_kp_, cose_signatures_config_, ledger_sign_mode_});
629 "Setting service signing identity to iss: {} sub: {}. Ledger "
630 "signature mode: {}",
631 cose_signatures_config_.
issuer,
632 cose_signatures_config_.
subject,
633 nlohmann::json(ledger_sign_mode_).dump());
638 if (!signing_identity.has_value())
640 throw std::logic_error(
641 "Called get_cose_signatures_config() before "
642 "set_service_signing_identity()");
645 return signing_identity->cose_signatures_config;
650 const auto delay = std::chrono::milliseconds(sig_ms_interval);
653 std::unique_lock<ccf::pal::Mutex> mguard(
656 bool should_emit_signature =
false;
658 if (mguard.try_lock())
663 auto sig_disp =
consensus->get_signature_disposition();
682 this->store.should_schedule_snapshot())
684 should_emit_signature =
true;
690 should_emit_signature =
true;
697 if (should_emit_signature)
708 if (emit_signature_periodic_task !=
nullptr)
710 emit_signature_periodic_task->cancel_task();
720 const std::vector<uint8_t>& hash_at_snapshot)
override
726 auto* tree_h = tx.template ro<ccf::SerialisedMerkleTree>(
727 ccf::Tables::SERIALISED_MERKLE_TREE);
728 auto tree = tree_h->get();
729 if (!tree.has_value())
737 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
740 !replicated_state_tree.in_range(1),
741 "Tree is not empty before initialising from snapshot");
743 replicated_state_tree.deserialise(tree.value());
747 hash_at_snapshot.begin(),
750 replicated_state_tree.append(hash);
756 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
757 return replicated_state_tree.get_root();
760 std::tuple<ccf::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
763 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
765 {term_of_last_version,
767 replicated_state_tree.get_root(),
768 term_of_next_version};
779 tx.template ro<ccf::Signatures>(ccf::Tables::SIGNATURES);
780 auto sig = signatures->get();
788 const auto sig_version = signatures->get_version_of_previous_write();
789 if (sig_version.has_value() && sig_version.value() == version)
791 if (!verify_node_signature(tx, sig->node, sig->sig, root))
798 auto* cose_signatures =
799 tx.template ro<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
800 auto cose_sig = cose_signatures->get();
802 if (!cose_sig.has_value())
811 LOG_FAIL_FMT(
"No signatures found in COSE signatures map");
820 const auto cose_sig_version =
821 cose_signatures->get_version_of_previous_write();
822 if (cose_sig_version.has_value() && cose_sig_version.value() != version)
825 "Non-monotonic presence of COSE signatures - had one at {} but none "
827 cose_sig_version.value(),
832 auto* service = tx.template ro<ccf::Service>(Tables::SERVICE);
833 auto service_info = service->get();
835 if (!service_info.has_value())
837 LOG_FAIL_FMT(
"No service key found to verify the signature");
841 std::vector<uint8_t> root_hash{
842 root.h.data(), root.h.data() + root.h.size()};
843 if (!cose_verifier_cached(service_info->cert)
844 ->verify_detached(cose_sig.value(), root_hash))
853 auto receipt = ccf::cose::decode_ccf_receipt(
854 cose_sig.value(),
false);
855 if (receipt.phdr.cwt.iat.has_value())
858 "Verified COSE signature for TxID {}, issued at {}",
859 receipt.phdr.ccf.txid,
860 ccf::ds::to_x509_time_string(
861 std::chrono::system_clock::from_time_t(
862 receipt.phdr.cwt.iat.value())));
865 catch (
const std::exception& e)
868 "Failed to decode COSE protected header for debug logging: {}",
878 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
879 if (to <= replicated_state_tree.end_index())
881 return replicated_state_tree.serialise(
882 replicated_state_tree.begin_index(), to);
892 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
893 term_of_last_version = t;
894 term_of_next_version = t;
900 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
902 term_of_last_version = tx_id.
view;
903 term_of_next_version = term_of_next_version_;
904 replicated_state_tree.retract(tx_id.
seqno);
905 log_hash(replicated_state_tree.get_root(),
ROLLBACK);
910 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
917 log_hash(replicated_state_tree.get_root(),
COMPACT);
924 std::unique_lock<ccf::pal::Mutex> mguard(
signature_lock, std::defer_lock);
946 if (!endorsed_cert.has_value())
948 throw std::logic_error(
949 fmt::format(
"No endorsed certificate set to emit signature"));
954 LOG_DEBUG_FMT(
"Signed at {} in view: {}", txid.seqno, txid.view);
956 if (!signing_identity.has_value())
958 throw std::logic_error(
959 fmt::format(
"No service key has been set yet to sign"));
970 *signing_identity->service_kp,
971 endorsed_cert.value(),
972 signing_identity->cose_signatures_config,
973 signing_identity->ledger_sign_mode,
980 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
981 return replicated_state_tree.get_proof(index).to_v();
987 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
988 return replicated_state_tree.verify(proof);
993 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
994 auto leaf = replicated_state_tree.get_leaf(index);
995 return {leaf.h.begin(), leaf.h.end()};
998 void append(
const std::vector<uint8_t>& data)
override
1002 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
1003 replicated_state_tree.append(rh);
1008 std::optional<ccf::kv::Term> expected_term_of_next_version =
1009 std::nullopt)
override
1011 log_hash(digest,
APPEND);
1012 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
1013 if (expected_term_of_next_version.has_value())
1015 if (expected_term_of_next_version.value() != term_of_next_version)
1020 replicated_state_tree.append(digest);
1025 endorsed_cert = cert;
1032 if (cert != cose_cert_cached)
1034 cose_cert_cached = cert;
1038 return cose_verifier;
#define CCF_ASSERT_FMT(expr,...)
Definition ccf_assert.h:10
void set_service_signing_identity(std::shared_ptr< ccf::crypto::ECKeyPair_OpenSSL > service_kp_, const ccf::COSESignaturesConfig &cose_signatures_config_) override
Definition history.h:613
~HashedTxHistory() override
Definition history.h:706
std::tuple< ccf::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term > get_replicated_state_txid_and_root() override
Definition history.h:761
void set_term(ccf::kv::Term t) override
Definition history.h:888
bool verify_proof(const std::vector< uint8_t > &v) override
Definition history.h:984
void set_endorsed_certificate(const ccf::crypto::Pem &cert) override
Definition history.h:1023
HashedTxHistory(ccf::kv::Store &store_, NodeId id_, ccf::crypto::ECKeyPair &node_kp_, size_t sig_tx_interval_=0, size_t sig_ms_interval_=0, bool signature_timer=false)
Definition history.h:594
void compact(ccf::kv::Version v) override
Definition history.h:908
std::vector< uint8_t > get_proof(ccf::kv::Version index) override
Definition history.h:978
ccf::pal::Mutex signature_lock
Definition history.h:920
const ccf::COSESignaturesConfig & get_cose_signatures_config() override
Definition history.h:636
void rollback(const ccf::TxID &tx_id, ccf::kv::Term term_of_next_version_) override
Definition history.h:897
std::vector< uint8_t > serialise_tree(size_t to) override
Definition history.h:876
bool verify_root_signatures(ccf::kv::Version version) override
Definition history.h:771
void append(const std::vector< uint8_t > &data) override
Definition history.h:998
void start_signature_emit_timer() override
Definition history.h:648
void set_node_id(const NodeId &id_)
Definition history.h:714
void try_emit_signature() override
Definition history.h:922
void emit_signature() override
Definition history.h:937
ccf::crypto::Sha256Hash get_replicated_state_root() override
Definition history.h:754
std::vector< uint8_t > get_raw_leaf(uint64_t index) override
Definition history.h:991
void append_entry(const ccf::crypto::Sha256Hash &digest, std::optional< ccf::kv::Term > expected_term_of_next_version=std::nullopt) override
Definition history.h:1006
bool init_from_snapshot(const std::vector< uint8_t > &hash_at_snapshot) override
Definition history.h:719
ccf::kv::PendingTxInfo call() override
Definition history.h:345
MerkleTreeHistoryPendingTx(ccf::TxID txid_, ccf::kv::Store &store_, ccf::kv::TxHistory &history_, NodeId id_, ccf::crypto::ECKeyPair &node_kp_, ccf::crypto::ECKeyPair_OpenSSL &service_kp_, ccf::crypto::Pem &endorsed_cert_, const ccf::COSESignaturesConfig &cose_signatures_config_, ccf::LedgerSignMode ledger_sign_mode_, std::unordered_map< std::string, CoseKey > &cose_key_cache_)
Definition history.h:322
void deserialise(const std::vector< uint8_t > &serialised)
Definition history.h:452
void flush(uint64_t index)
Definition history.h:480
ccf::crypto::Sha256Hash get_root() const
Definition history.h:462
std::vector< uint8_t > serialise(size_t from, size_t to)
Definition history.h:525
ccf::crypto::Sha256Hash get_leaf(uint64_t index)
Definition history.h:552
MerkleTreeHistory(const std::vector< uint8_t > &serialised)
Definition history.h:442
~MerkleTreeHistory()=default
MerkleTreeHistory & operator=(const MerkleTreeHistory &rhs)
Definition history.h:470
MerkleTreeHistory(ccf::crypto::Sha256Hash first_hash={})
Definition history.h:446
bool verify(const Proof &r)
Definition history.h:512
MerkleTreeHistory(MerkleTreeHistory const &)=delete
Proof get_proof(uint64_t index)
Definition history.h:492
std::vector< uint8_t > serialise()
Definition history.h:517
uint64_t end_index()
Definition history.h:542
void append(const ccf::crypto::Sha256Hash &hash)
Definition history.h:457
uint64_t begin_index()
Definition history.h:537
void retract(uint64_t index)
Definition history.h:486
bool in_range(uint64_t index)
Definition history.h:547
ccf::kv::PendingTxInfo call() override
Definition history.h:96
NullTxHistoryPendingTx(ccf::TxID txid_, ccf::kv::Store &store_, NodeId id_)
Definition history.h:89
void set_endorsed_certificate(const ccf::crypto::Pem &cert) override
Definition history.h:228
void try_emit_signature() override
Definition history.h:183
void compact(ccf::kv::Version) override
Definition history.h:162
ccf::crypto::Sha256Hash get_replicated_state_root() override
Definition history.h:199
ccf::kv::Term term_of_last_version
Definition history.h:121
void start_signature_emit_timer() override
Definition history.h:185
bool verify_root_signatures(ccf::kv::Version) override
Definition history.h:144
bool init_from_snapshot(const std::vector< uint8_t > &) override
Definition history.h:164
std::vector< uint8_t > serialise_tree(size_t) override
Definition history.h:223
void emit_signature() override
Definition history.h:175
ccf::kv::Term term_of_next_version
Definition history.h:122
bool verify_proof(const std::vector< uint8_t > &) override
Definition history.h:218
void append(const std::vector< uint8_t > &) override
Definition history.h:131
std::vector< uint8_t > get_proof(ccf::kv::Version) override
Definition history.h:213
NullTxHistory(ccf::kv::Store &store_, NodeId id_, ccf::crypto::ECKeyPair &)
Definition history.h:125
void set_term(ccf::kv::Term t) override
Definition history.h:149
std::tuple< ccf::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term > get_replicated_state_txid_and_root() override
Definition history.h:205
void append_entry(const ccf::crypto::Sha256Hash &, std::optional< ccf::kv::Term >=std::nullopt) override
Definition history.h:136
ccf::kv::Version version
Definition history.h:120
const ccf::COSESignaturesConfig & get_cose_signatures_config() override
Definition history.h:194
void set_service_signing_identity(std::shared_ptr< ccf::crypto::ECKeyPair_OpenSSL > service_kp_, const ccf::COSESignaturesConfig &) override
Definition history.h:187
void rollback(const ccf::TxID &tx_id, ccf::kv::Term commit_term_) override
Definition history.h:155
std::vector< uint8_t > get_raw_leaf(uint64_t) override
Definition history.h:170
std::shared_ptr< HistoryTree::Path > get_path()
Definition history.h:270
const HistoryTree::Hash & get_root() const
Definition history.h:265
std::vector< uint8_t > to_v() const
Definition history.h:298
Proof(HistoryTree *tree, uint64_t index)
Definition history.h:275
Proof(const std::vector< uint8_t > &v)
Definition history.h:258
Proof(const Proof &)=delete
bool verify(HistoryTree *tree) const
Definition history.h:282
Definition ec_key_pair.h:16
std::vector< uint8_t > private_key_der() const override
Definition ec_key_pair.cpp:132
std::vector< uint8_t > public_key_der() const override
Definition ec_key_pair.cpp:127
Definition ec_key_pair.h:19
virtual std::vector< uint8_t > sign_hash(const uint8_t *hash, size_t hash_size) const =0
Definition sha256_hash.h:16
Representation h
Definition sha256_hash.h:20
static constexpr size_t SIZE
Definition sha256_hash.h:18
Definition kv_types.h:452
ReservedTx create_reserved_tx(const TxID &tx_id)
Definition store.h:1321
ReadOnlyTx create_read_only_tx() override
Definition store.h:1296
size_t committable_gap() override
Definition store.h:1150
TxID next_txid() override
Definition store.h:1142
std::shared_ptr< Consensus > get_consensus() override
Definition store.h:183
CommitResult commit(const TxID &txid, std::unique_ptr< PendingTx > pending_tx, bool globally_committable) override
Definition store.h:903
Definition kv_types.h:332
virtual std::vector< uint8_t > serialise_tree(size_t to)=0
virtual ccf::crypto::Sha256Hash get_replicated_state_root()=0
static bool ok(LoggerLevel l)
Definition logger.h:232
int cose_sign_ledger(const CoseEvpKey *key, const uint8_t *kid_ptr, size_t kid_len, int64_t iat, const uint8_t *issuer_ptr, size_t issuer_len, const uint8_t *subject_ptr, size_t subject_len, const uint8_t *txid_ptr, size_t txid_len, const uint8_t *payload_ptr, size_t payload_len, uint8_t **out_ptr, size_t *out_len, uint8_t **err_ptr, size_t *err_len)
#define LOG_INFO_FMT
Definition internal_logger.h:15
#define LOG_TRACE_FMT
Definition internal_logger.h:13
#define LOG_DEBUG_FMT
Definition internal_logger.h:14
#define LOG_FAIL_FMT
Definition internal_logger.h:16
std::unique_ptr< COSEVerifier > COSEVerifierUniquePtr
Definition cose_verifier.h:28
COSEVerifierUniquePtr make_cose_verifier_from_pem_cert(const Pem &pem)
Definition cose_verifier.cpp:280
std::string kid_from_key(const std::vector< uint8_t > &public_key_der)
Definition public_key.cpp:10
uint64_t Term
Definition kv_types.h:46
uint64_t Version
Definition version.h:10
std::mutex Mutex
Definition locking.h:12
Task make_basic_task(Ts &&... ts)
Definition basic_task.h:33
void add_periodic_task(Task task, std::chrono::milliseconds initial_delay, std::chrono::milliseconds repeat_period)
Definition task_system.cpp:75
std::shared_ptr< BaseTask > Task
Definition task.h:36
Definition app_interface.h:13
merkle::TreeT< sha256_byte_size, ccf::sha256_history > HistoryTree
Definition history.h:247
constexpr int MAX_HISTORY_LEN
Definition history.h:50
std::vector< uint8_t > CoseSignature
Definition signatures.h:64
LedgerSignMode get_ledger_sign_mode()
Definition get_ledger_sign_mode_cose.cpp:8
HashOp
Definition history.h:40
@ COMPACT
Definition history.h:44
@ VERIFY
Definition history.h:42
@ APPEND
Definition history.h:41
@ ROLLBACK
Definition history.h:43
LedgerSignMode
Definition ledger_sign_mode.h:12
Definition consensus_types.h:23
Definition cose_signatures_config.h:12
std::string issuer
Definition cose_signatures_config.h:13
std::string subject
Definition cose_signatures_config.h:14
Definition signatures.h:14
SeqNo seqno
Definition tx_id.h:46
View view
Definition tx_id.h:45
std::string to_str() const
Definition tx_id.h:48
Definition kv_types.h:430