CCF
Loading...
Searching...
No Matches
cose_common.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
4#pragma once
5
7#include <qcbor/qcbor.h>
8#include <qcbor/qcbor_spiffy_decode.h>
9#include <stdexcept>
10#include <string>
11#include <t_cose/t_cose_common.h>
12
13namespace ccf::cose
14{
15 namespace headers
16 {
17 static constexpr int64_t PARAM_ALG = 1;
18 static constexpr int64_t PARAM_CONTENT_TYPE = 3;
19 static constexpr int64_t PARAM_KID = 4;
20 static constexpr int64_t PARAM_X5CHAIN = 33;
21
22 static constexpr auto CONTENT_TYPE_APPLICATION_JSON_VALUE =
23 "application/json";
24 }
25
26 using Signature = std::span<const uint8_t>;
27
28 static std::string qcbor_buf_to_string(const UsefulBufC& buf)
29 {
30 return std::string(reinterpret_cast<const char*>(buf.ptr), buf.len);
31 }
32
33 static std::vector<uint8_t> qcbor_buf_to_byte_vector(const UsefulBufC& buf)
34 {
35 auto ptr = static_cast<const uint8_t*>(buf.ptr);
36 return {ptr, ptr + buf.len};
37 }
38
39 static bool is_ecdsa_alg(int64_t cose_alg)
40 {
41 return cose_alg == T_COSE_ALGORITHM_ES256 ||
42 cose_alg == T_COSE_ALGORITHM_ES384 || cose_alg == T_COSE_ALGORITHM_ES512;
43 }
44
45 static bool is_rsa_alg(int64_t cose_alg)
46 {
47 return cose_alg == T_COSE_ALGORITHM_PS256 ||
48 cose_alg == T_COSE_ALGORITHM_PS384 || cose_alg == T_COSE_ALGORITHM_PS512;
49 }
50
51 struct COSEDecodeError : public std::runtime_error
52 {
53 COSEDecodeError(const std::string& msg) : std::runtime_error(msg) {}
54 };
55
56 struct COSESignatureValidationError : public std::runtime_error
57 {
58 COSESignatureValidationError(const std::string& msg) :
59 std::runtime_error(msg)
60 {}
61 };
62
63 static std::string tstring_to_string(QCBORItem& item)
64 {
65 return {
66 static_cast<const char*>(item.val.string.ptr),
67 static_cast<const char*>(item.val.string.ptr) + item.val.string.len};
68 }
69
70 static std::pair<std::string /* issuer */, std::string /* subject */>
71 extract_iss_sub_from_sig(const std::vector<uint8_t>& cose_sign1)
72 {
73 QCBORError qcbor_result;
74 QCBORDecodeContext ctx;
75 UsefulBufC buf{cose_sign1.data(), cose_sign1.size()};
76 QCBORDecode_Init(&ctx, buf, QCBOR_DECODE_MODE_NORMAL);
77
78 QCBORDecode_EnterArray(&ctx, nullptr);
79 qcbor_result = QCBORDecode_GetError(&ctx);
80 if (qcbor_result != QCBOR_SUCCESS)
81 {
82 throw COSEDecodeError("Failed to parse COSE_Sign1 outer array");
83 }
84
85 uint64_t tag = QCBORDecode_GetNthTagOfLast(&ctx, 0);
86 if (tag != CBOR_TAG_COSE_SIGN1)
87 {
88 throw COSEDecodeError("COSE_Sign1 is not tagged");
89 }
90
91 QCBORDecode_EnterBstrWrapped(&ctx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
92 QCBORDecode_EnterMap(&ctx, NULL);
93
94 enum
95 {
96 CWT_CLAIMS_INDEX,
97 END_INDEX,
98 };
99 QCBORItem header_items[END_INDEX + 1];
100
101 header_items[CWT_CLAIMS_INDEX].label.int64 = crypto::COSE_PHEADER_KEY_CWT;
102 header_items[CWT_CLAIMS_INDEX].uLabelType = QCBOR_TYPE_INT64;
103 header_items[CWT_CLAIMS_INDEX].uDataType = QCBOR_TYPE_MAP;
104
105 header_items[END_INDEX].uLabelType = QCBOR_TYPE_NONE;
106
107 QCBORDecode_GetItemsInMap(&ctx, header_items);
108
109 qcbor_result = QCBORDecode_GetError(&ctx);
110 if (qcbor_result != QCBOR_SUCCESS)
111 {
112 throw COSEDecodeError(
113 fmt::format("Failed to decode protected header: {}", qcbor_result));
114 }
115
116 if (header_items[CWT_CLAIMS_INDEX].uDataType == QCBOR_TYPE_NONE)
117 {
118 throw COSEDecodeError("Missing CWT claims in COSE_Sign1");
119 }
120
121 QCBORDecode_EnterMapFromMapN(&ctx, crypto::COSE_PHEADER_KEY_CWT);
122 auto decode_error = QCBORDecode_GetError(&ctx);
123 if (decode_error != QCBOR_SUCCESS)
124 {
125 throw COSEDecodeError(
126 fmt::format("Failed to decode CWT claims: {}", decode_error));
127 }
128
129 enum
130 {
131 CWT_ISS_INDEX,
132 CWT_SUB_INDEX,
133 CWT_END_INDEX,
134 };
135 QCBORItem cwt_items[CWT_END_INDEX + 1];
136
137 cwt_items[CWT_ISS_INDEX].label.int64 = crypto::COSE_PHEADER_KEY_ISS;
138 cwt_items[CWT_ISS_INDEX].uLabelType = QCBOR_TYPE_INT64;
139 cwt_items[CWT_ISS_INDEX].uDataType = QCBOR_TYPE_TEXT_STRING;
140
141 cwt_items[CWT_SUB_INDEX].label.int64 = crypto::COSE_PHEADER_KEY_SUB;
142 cwt_items[CWT_SUB_INDEX].uLabelType = QCBOR_TYPE_INT64;
143 cwt_items[CWT_SUB_INDEX].uDataType = QCBOR_TYPE_TEXT_STRING;
144
145 cwt_items[CWT_END_INDEX].uLabelType = QCBOR_TYPE_NONE;
146
147 QCBORDecode_GetItemsInMap(&ctx, cwt_items);
148 decode_error = QCBORDecode_GetError(&ctx);
149 if (decode_error != QCBOR_SUCCESS)
150 {
151 throw COSEDecodeError(
152 fmt::format("Failed to decode CWT claim contents: {}", decode_error));
153 }
154
155 if (
156 cwt_items[CWT_ISS_INDEX].uDataType != QCBOR_TYPE_NONE &&
157 cwt_items[CWT_SUB_INDEX].uDataType != QCBOR_TYPE_NONE)
158 {
159 auto issuer = tstring_to_string(cwt_items[CWT_ISS_INDEX]);
160 auto subject = tstring_to_string(cwt_items[CWT_SUB_INDEX]);
161 return {issuer, subject};
162 }
163 else
164 {
165 throw COSEDecodeError(
166 "Missing issuer and subject values in CWT Claims in COSE_Sign1");
167 }
168 }
169}
Definition cose_signatures_config_interface.h:12
std::span< const uint8_t > Signature
Definition cose_common.h:26
std::vector< uint8_t > cose_sign1(const KeyPair_OpenSSL &key, const std::vector< std::shared_ptr< COSEParametersFactory > > &protected_headers, std::span< const uint8_t > payload, bool detached_payload)
Definition cose_sign.cpp:231
STL namespace.
Definition cose_common.h:52
COSEDecodeError(const std::string &msg)
Definition cose_common.h:53
Definition cose_common.h:57
COSESignatureValidationError(const std::string &msg)
Definition cose_common.h:58