1010#include " ds/internal_logger.h"
1111#include " x509_time.h"
1212
13+ #include < crypto/cbor.h>
1314#include < openssl/evp.h>
1415#include < openssl/ossl_typ.h>
1516#include < openssl/x509.h>
@@ -27,72 +28,27 @@ namespace
2728 std::optional<int > extract_algorithm_from_header (
2829 std::span<const uint8_t > cose_msg)
2930 {
30- UsefulBufC msg{cose_msg.data (), cose_msg.size ()};
31- QCBORError qcbor_result = QCBOR_SUCCESS;
31+ using namespace ccf ::cbor;
3232
33- QCBORDecodeContext ctx;
34- QCBORDecode_Init (&ctx, msg, QCBOR_DECODE_MODE_NORMAL );
33+ auto cose_cbor =
34+ rethrow_with_msg ([&]() { return parse (cose_msg); }, " Parse COSE CBOR " );
3535
36- QCBORDecode_EnterArray (&ctx, nullptr );
37- qcbor_result = QCBORDecode_GetError (&ctx);
38- if (qcbor_result != QCBOR_SUCCESS)
39- {
40- LOG_DEBUG_FMT (" Failed to parse COSE_Sign1 outer array" );
41- return std::nullopt ;
42- }
43-
44- const uint64_t tag = QCBORDecode_GetNthTagOfLast (&ctx, 0 );
45- if (tag != CBOR_TAG_COSE_SIGN1)
46- {
47- LOG_DEBUG_FMT (" Failed to parse COSE_Sign1 tag" );
48- return std::nullopt ;
49- }
50-
51- q_useful_buf_c protected_parameters = {};
52- QCBORDecode_EnterBstrWrapped (
53- &ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &protected_parameters);
54- QCBORDecode_EnterMap (&ctx, nullptr );
55-
56- enum HeaderIndex : uint8_t
57- {
58- ALG_INDEX,
59- END_INDEX
60- };
61- QCBORItem header_items[END_INDEX + 1 ];
62-
63- header_items[ALG_INDEX].label .int64 = ccf::crypto::COSE_PHEADER_KEY_ALG;
64- header_items[ALG_INDEX].uLabelType = QCBOR_TYPE_INT64;
65- header_items[ALG_INDEX].uDataType = QCBOR_TYPE_INT64;
66-
67- header_items[END_INDEX].uLabelType = QCBOR_TYPE_NONE;
68-
69- QCBORDecode_GetItemsInMap (&ctx, static_cast <QCBORItem*>(header_items));
70- qcbor_result = QCBORDecode_GetError (&ctx);
71- if (qcbor_result != QCBOR_SUCCESS)
72- {
73- LOG_DEBUG_FMT (" Failed to decode protected header" );
74- return std::nullopt ;
75- }
36+ const auto & cose_envelope = rethrow_with_msg (
37+ [&]() -> auto & { return cose_cbor->tag_at (18 ); }, " Parse COSE tag" );
7638
77- if (header_items[ALG_INDEX].uDataType == QCBOR_TYPE_NONE)
78- {
79- LOG_DEBUG_FMT (" Failed to retrieve (missing) 'alg' parameter" );
80- return std::nullopt ;
81- }
39+ const auto & phdr_raw = rethrow_with_msg (
40+ [&]() -> auto & { return cose_envelope->array_at (0 ); },
41+ " Parse raw protected header" );
8242
83- const int alg = header_items[ALG_INDEX].val .int64 ;
43+ auto phdr = rethrow_with_msg (
44+ [&]() { return parse (phdr_raw->as_bytes ()); }, " Decode protected header" );
8445
85- // Complete decode to ensure well-formed CBOR.
86-
87- QCBORDecode_ExitMap (&ctx);
88- QCBORDecode_ExitBstrWrapped (&ctx);
89-
90- qcbor_result = QCBORDecode_GetError (&ctx);
91- if (qcbor_result != QCBOR_SUCCESS)
92- {
93- LOG_DEBUG_FMT (" Failed to decode protected header: {}" , qcbor_result);
94- return std::nullopt ;
95- }
46+ const int64_t alg = rethrow_with_msg (
47+ [&]() {
48+ return phdr->map_at (make_signed (ccf::crypto::COSE_PHEADER_KEY_ALG))
49+ ->as_signed ();
50+ },
51+ " Retrieve alg from protected header" );
9652
9753 return alg;
9854 }
@@ -250,104 +206,42 @@ namespace ccf::crypto
250206 COSEEndorsementValidity extract_cose_endorsement_validity (
251207 std::span<const uint8_t > cose_msg)
252208 {
253- UsefulBufC msg{cose_msg.data (), cose_msg.size ()};
254- QCBORError qcbor_result = QCBOR_SUCCESS;
255-
256- QCBORDecodeContext ctx;
257- QCBORDecode_Init (&ctx, msg, QCBOR_DECODE_MODE_NORMAL);
258-
259- QCBORDecode_EnterArray (&ctx, nullptr );
260- qcbor_result = QCBORDecode_GetError (&ctx);
261- if (qcbor_result != QCBOR_SUCCESS)
262- {
263- throw std::logic_error (" Failed to parse COSE_Sign1 outer array" );
264- }
265-
266- const uint64_t tag = QCBORDecode_GetNthTagOfLast (&ctx, 0 );
267- if (tag != CBOR_TAG_COSE_SIGN1)
268- {
269- throw std::logic_error (" Failed to parse COSE_Sign1 tag" );
270- }
271-
272- q_useful_buf_c protected_parameters = {};
273-
274- QCBORDecode_EnterBstrWrapped (
275- &ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &protected_parameters);
276-
277- qcbor_result = QCBORDecode_GetError (&ctx);
278- if (qcbor_result != QCBOR_SUCCESS)
279- {
280- throw std::logic_error (" Failed to parse COSE_Sign1 as bstr" );
281- }
282-
283- QCBORDecode_EnterMap (&ctx, nullptr ); // phdr
284- QCBORDecode_EnterMapFromMapSZ (&ctx, " ccf.v1" ); // phdr["ccf.v1"]
285-
286- qcbor_result = QCBORDecode_GetError (&ctx);
287- if (qcbor_result != QCBOR_SUCCESS)
288- {
289- throw std::logic_error (" Failed to parse COSE_Sign1 wrapped map" );
290- }
291-
292- enum HeaderIndex : uint8_t
293- {
294- FROM_INDEX,
295- TO_INDEX,
296- END_INDEX
297- };
298- QCBORItem header_items[END_INDEX + 1 ];
299-
300- header_items[FROM_INDEX].label .string = UsefulBufC{
301- ccf::crypto::COSE_PHEADER_KEY_RANGE_BEGIN.data (),
302- ccf::crypto::COSE_PHEADER_KEY_RANGE_BEGIN.size ()};
303- header_items[FROM_INDEX].uLabelType = QCBOR_TYPE_TEXT_STRING;
304- header_items[FROM_INDEX].uDataType = QCBOR_TYPE_TEXT_STRING;
305-
306- header_items[TO_INDEX].label .string = UsefulBufC{
307- ccf::crypto::COSE_PHEADER_KEY_RANGE_END.data (),
308- ccf::crypto::COSE_PHEADER_KEY_RANGE_END.size ()};
309- header_items[TO_INDEX].uLabelType = QCBOR_TYPE_TEXT_STRING;
310- header_items[TO_INDEX].uDataType = QCBOR_TYPE_TEXT_STRING;
311-
312- header_items[END_INDEX].uLabelType = QCBOR_TYPE_NONE;
313-
314- QCBORDecode_GetItemsInMap (&ctx, static_cast <QCBORItem*>(header_items));
315- qcbor_result = QCBORDecode_GetError (&ctx);
316- if (qcbor_result != QCBOR_SUCCESS)
317- {
318- throw std::logic_error (" Failed to decode protected header" );
319- }
320-
321- if (header_items[FROM_INDEX].uDataType == QCBOR_TYPE_NONE)
322- {
323- throw std::logic_error (fmt::format (
324- " Failed to retrieve (missing) {} parameter" ,
325- ccf::crypto::COSE_PHEADER_KEY_RANGE_BEGIN));
326- }
327-
328- if (header_items[TO_INDEX].uDataType == QCBOR_TYPE_NONE)
329- {
330- throw std::logic_error (fmt::format (
331- " Failed to retrieve (missing) {} parameter" ,
332- ccf::crypto::COSE_PHEADER_KEY_RANGE_END));
333- }
334-
335- const auto from = qcbor_buf_to_string (header_items[FROM_INDEX].val .string );
336- const auto to = qcbor_buf_to_string (header_items[TO_INDEX].val .string );
337-
338- // Complete decode to ensure well-formed CBOR.
339-
340- QCBORDecode_ExitMap (&ctx); // phdr["ccf.v1"]
341- QCBORDecode_ExitMap (&ctx); // phdr
342- QCBORDecode_ExitBstrWrapped (&ctx);
343-
344- qcbor_result = QCBORDecode_GetError (&ctx);
345- if (qcbor_result != QCBOR_SUCCESS)
346- {
347- throw std::logic_error (fmt::format (
348- " Failed to decode protected header with error code: {}" , qcbor_result));
349- }
350-
351- return COSEEndorsementValidity{.from_txid = from, .to_txid = to};
209+ using namespace ccf ::cbor;
210+
211+ auto cose_cbor =
212+ rethrow_with_msg ([&]() { return parse (cose_msg); }, " Parse COSE CBOR" );
213+
214+ const auto & cose_envelope = rethrow_with_msg (
215+ [&]() -> auto & { return cose_cbor->tag_at (18 ); }, " Parse COSE tag" );
216+
217+ const auto & phdr_raw = rethrow_with_msg (
218+ [&]() -> auto & { return cose_envelope->array_at (0 ); },
219+ " Parse raw protected header" );
220+
221+ auto phdr = rethrow_with_msg (
222+ [&]() { return parse (phdr_raw->as_bytes ()); }, " Decode protected header" );
223+
224+ const auto & ccf_claims = rethrow_with_msg (
225+ [&]() -> auto & {
226+ return phdr->map_at (make_string (ccf::crypto::COSE_PHEADER_KEY_CCF));
227+ },
228+ " Retrieve CCF claims" );
229+
230+ auto from = rethrow_with_msg (
231+ [&]() {
232+ return ccf_claims->map_at (make_string (COSE_PHEADER_KEY_RANGE_BEGIN))
233+ ->as_string ();
234+ },
235+ " Retrieve epoch range begin" );
236+
237+ auto to = rethrow_with_msg (
238+ [&]() {
239+ return ccf_claims->map_at (make_string (COSE_PHEADER_KEY_RANGE_END))
240+ ->as_string ();
241+ },
242+ " Retrieve epoch range end" );
243+
244+ return COSEEndorsementValidity{
245+ .from_txid = std::string (from), .to_txid = std::string (to)};
352246 }
353247}
0 commit comments