10#include <crypto/cose.h>
22 static bool is_ecdsa_alg(int64_t cose_alg)
25 constexpr int COSE_ALGORITHM_ES256 = -7;
26 constexpr int COSE_ALGORITHM_ES384 = -35;
27 constexpr int COSE_ALGORITHM_ES512 = -36;
28 return cose_alg == COSE_ALGORITHM_ES256 ||
29 cose_alg == COSE_ALGORITHM_ES384 || cose_alg == COSE_ALGORITHM_ES512;
32 static bool is_rsa_alg(int64_t cose_alg)
35 constexpr int COSE_ALGORITHM_PS256 = -37;
36 constexpr int COSE_ALGORITHM_PS384 = -38;
37 constexpr int COSE_ALGORITHM_PS512 = -39;
38 return cose_alg == COSE_ALGORITHM_PS256 ||
39 cose_alg == COSE_ALGORITHM_PS384 || cose_alg == COSE_ALGORITHM_PS512;
50 std::runtime_error(msg)
56 std::optional<int64_t>
iat;
59 std::optional<int64_t>
svn;
65 std::optional<std::variant<int64_t, std::string>>
cty;
66 std::vector<std::vector<uint8_t>>
x5chain;
74 const auto& cwt_claims = rethrow_with_msg(
76 return cbor->map_at(make_signed(ccf::cose::header::iana::CWT_CLAIMS));
78 "Parse CWT claims map");
82 claims.
iat = cwt_claims->map_at(make_signed(ccf::cwt::header::iana::IAT))
92 return cwt_claims->map_at(make_signed(ccf::cwt::header::iana::ISS))
96 "Parse CWT claim iss({}) field", ccf::cwt::header::iana::ISS));
100 return cwt_claims->map_at(make_signed(ccf::cwt::header::iana::SUB))
104 "Parse CWT claim sub({}) field", ccf::cwt::header::iana::SUB));
109 cwt_claims->map_at(make_string(ccf::cwt::header::custom::SVN))
118 static Sign1ProtectedHeader decode_sign1_protected_header(
122 Sign1ProtectedHeader hdr;
126 return phdr->map_at(make_signed(ccf::cose::header::iana::ALG))
130 "Parse protected header alg({})", ccf::cose::header::iana::ALG));
135 phdr->map_at(make_signed(ccf::cose::header::iana::CONTENT_TYPE));
138 hdr.cty = std::string(cty->as_string());
142 hdr.cty = cty->as_signed();
152 const auto& x5chain_val =
153 phdr->map_at(make_signed(ccf::cose::header::iana::X5CHAIN));
157 "Parse protected header x5chain({})",
158 ccf::cose::header::iana::X5CHAIN));
160 decode_cwt_claims(phdr, hdr.cwt);
189 std::vector<std::pair<int64_t, std::vector<uint8_t>>>
path;
199 static std::vector<uint8_t> recompute_merkle_root(
const MerkleProof& proof)
206 "Unsupported write set digest size in Merkle proof leaf: {}",
211 throw COSEDecodeError(fmt::format(
212 "Unsupported claims digest size in Merkle proof leaf: {}",
216 std::span<const uint8_t, ccf::crypto::Sha256Hash::SIZE> wsd{
218 std::span<const uint8_t, ccf::crypto::Sha256Hash::SIZE> cd{
225 for (
const auto& element : proof.path)
229 std::span<const uint8_t, ccf::crypto::Sha256Hash::SIZE> sibling{
236 std::span<const uint8_t, ccf::crypto::Sha256Hash::SIZE> sibling{
243 return {leaf_digest.h.begin(), leaf_digest.h.end()};
246 static void decode_ccf_claims(
const ccf::cbor::Value& cbor, CcfClaims& claims)
252 return cbor->map_at(make_string(ccf::cose::header::custom::CCF_V1));
254 "Parse CCF claims map");
258 return ccf_claims->map_at(make_string(ccf::cose::header::custom::TX_ID))
262 "Parse CCF claims TxID ({}) field", ccf::cose::header::custom::TX_ID));
269 CcfCoseReceiptPhdr phdr{};
273 return cbor->map_at(make_signed(ccf::cose::header::iana::ALG))
277 "Parse protected header alg({})", ccf::cose::header::iana::ALG));
282 cbor->map_at(make_signed(ccf::cose::header::iana::KID))->as_bytes();
283 phdr.kid.assign(bytes.begin(), bytes.end());
286 "Parse protected header kid({})", ccf::cose::header::iana::KID));
290 return cbor->map_at(make_signed(ccf::cose::header::iana::VDS))
294 "Parse protected header vds({})", ccf::cose::header::iana::VDS));
296 if (phdr.vds != ccf::cose::value::CCF_LEDGER_SHA256)
298 throw COSEDecodeError(fmt::format(
299 "Unsupported vds value ({}) in protected header", phdr.vds));
302 decode_cwt_claims(cbor, phdr.cwt);
303 decode_ccf_claims(cbor, phdr.ccf);
308 static std::vector<MerkleProof> decode_merkle_proofs(
314 [&]() ->
auto& {
return cbor->array_at(1); },
315 "Parse unprotected header map");
319 return uhdr->map_at(make_signed(ccf::cose::header::iana::VDP));
321 fmt::format(
"Parse vdp() map", ccf::cose::header::iana::VDP));
326 make_signed(ccf::cose::header::iana::INCLUSION_PROOFS));
328 "Parse inclusion proofs");
330 std::vector<MerkleProof> proofs;
334 if (proofs_array->size() == 0)
336 throw CBORDecodeError(Error::DECODE_FAILED,
"Empty proofs array");
339 "Check proofs array");
341 for (
size_t i = 0; i < proofs_array->size(); ++i)
344 [&]() {
return parse(proofs_array->array_at(i)->as_bytes()); },
345 "Parse an encoded proof");
349 return cbor_proof->map_at(
352 "Parse proof: leaf");
360 proof.leaf.write_set_digest.assign(bytes.begin(), bytes.end());
362 "Parse leaf at wsd");
372 const auto& bytes = leaf->array_at(2)->as_bytes();
373 proof.leaf.claims_digest.assign(bytes.begin(), bytes.end());
379 return cbor_proof->map_at(
382 "Parse proof: path");
386 if (cbor_path->size() == 0)
388 throw CBORDecodeError(Error::DECODE_FAILED,
"Empty path");
391 "Check proof: path");
393 for (
size_t j = 0; j < cbor_path->size(); j++)
395 std::pair<int64_t, std::vector<uint8_t>> path_item;
397 [&]() ->
auto& {
return cbor_path->array_at(j); },
"Parse path link");
400 [&]() {
return simple_to_boolean(link->array_at(0)->as_simple()); },
401 "Parse path element at direction"));
404 const auto& bytes = link->array_at(1)->as_bytes();
405 path_item.second.assign(bytes.begin(), bytes.end());
407 "Parse path element at hash");
408 proof.path.push_back(path_item);
411 proofs.push_back(proof);
417 static CcfCoseReceipt decode_ccf_receipt(
418 const std::vector<uint8_t>& cose_sign1,
bool recompute_root)
426 [&]() ->
auto& {
return cose_cbor->tag_at(ccf::cbor::tag::COSE_SIGN_1); },
430 [&]() ->
auto& {
return cose_envelope->array_at(0); },
431 "Parse raw protected header");
434 [&]() {
return parse(phdr_raw->as_bytes()); },
"Parse protected header");
436 CcfCoseReceipt receipt;
438 receipt.phdr = decode_ccf_receipt_phdr(phdr);
442 auto proofs = decode_merkle_proofs(cose_envelope);
445 throw COSEDecodeError(
"No Merkle proofs found in COSE receipt");
448 receipt.merkle_root = recompute_merkle_root(proofs[0]);
449 receipt.claims_digest = proofs[0].leaf.claims_digest;
450 for (
size_t i = 1; i < proofs.size(); ++i)
452 auto root = recompute_merkle_root(proofs[i]);
453 if (root != receipt.merkle_root)
455 throw COSEDecodeError(
456 "Inconsistent Merkle roots computed from COSE receipt proofs");
458 if (proofs[i].leaf.claims_digest != receipt.claims_digest)
460 throw COSEDecodeError(fmt::format(
461 "Claims from proofs don't match: {} != {}",
462 ds::to_hex(receipt.claims_digest),
463 ds::to_hex(proofs[i].leaf.claims_digest)));
Definition sha256_hash.h:16
static Sha256Hash from_span(const std::span< const uint8_t, SIZE > &sp)
Definition sha256_hash.cpp:69
static constexpr size_t SIZE
Definition sha256_hash.h:18
decltype(auto) rethrow_with_msg(auto &&f, std::string_view msg={})
Definition cbor.h:123
std::shared_ptr< ValueImpl > Value
Definition cbor.h:26
std::vector< std::vector< uint8_t > > parse_x5chain(const ccf::cbor::Value &x5chain_value)
Definition cose_utils.h:10
Definition cose_signatures_config_interface.h:12
std::span< const uint8_t > Signature
Definition cose_common.h:20
uint64_t element
Definition sharing.cpp:20
Definition app_interface.h:13
@ RIGHT
Definition receipt.h:151
@ LEFT
Definition receipt.h:150
@ MERKLE_PROOF_LEAF_LABEL
Definition receipt.h:142
@ MERKLE_PROOF_PATH_LABEL
Definition receipt.h:143
Definition cose_common.h:43
COSEDecodeError(const std::string &msg)
Definition cose_common.h:44
Definition cose_common.h:48
COSESignatureValidationError(const std::string &msg)
Definition cose_common.h:49
Definition cose_common.h:166
std::string txid
Definition cose_common.h:167
Definition cose_common.h:171
CwtClaims cwt
Definition cose_common.h:174
std::vector< uint8_t > kid
Definition cose_common.h:173
int vds
Definition cose_common.h:176
int alg
Definition cose_common.h:172
Definition cose_common.h:193
std::vector< uint8_t > merkle_root
Definition cose_common.h:195
std::vector< uint8_t > claims_digest
Definition cose_common.h:196
CcfCoseReceiptPhdr phdr
Definition cose_common.h:194
Definition cose_common.h:55
std::optional< int64_t > svn
Definition cose_common.h:59
std::string sub
Definition cose_common.h:58
std::optional< int64_t > iat
Definition cose_common.h:56
std::string iss
Definition cose_common.h:57
Definition cose_common.h:180
std::vector< uint8_t > claims_digest
Definition cose_common.h:183
std::string commit_evidence
Definition cose_common.h:182
std::vector< uint8_t > write_set_digest
Definition cose_common.h:181
Definition cose_common.h:187
std::vector< std::pair< int64_t, std::vector< uint8_t > > > path
Definition cose_common.h:189
Leaf leaf
Definition cose_common.h:188