34 using EltW =
typename LogicCircuit::EltW;
35 using Elt =
typename LogicCircuit::Elt;
36 using Nat =
typename Field::N;
40 using v8 =
typename LogicCircuit::v8;
41 using v32 =
typename LogicCircuit::v32;
42 using v256 =
typename LogicCircuit::v256;
43 using vind =
typename LogicCircuit::template bitvec<kMdoc1CborIndexBits>;
47 using Routing = Routing<LogicCircuit>;
48 using ShaBlockWitness =
typename Flatsha::BlockWitness;
49 using sha_packed_v32 =
typename Flatsha::packed_v32;
50 using Cbor = Cbor<LogicCircuit, kMdoc1CborIndexBits>;
52 const LogicCircuit& lc_;
59 void input(
const LogicCircuit& lc) {
60 k = lc.template vinput<kMdoc1CborIndexBits>();
61 v = lc.template vinput<kMdoc1CborIndexBits>();
62 ndx = lc.template vinput<kMdoc1CborIndexBits>();
69 void input(
const LogicCircuit& lc) {
70 offset = lc.template vinput<kMdoc1CborIndexBits>();
71 len = lc.template vinput<kMdoc1CborIndexBits>();
81 EcdsaWitness dpk_sig_;
83 v8 in_[64 * kMdoc1MaxSHABlocks];
85 ShaBlockWitness sig_sha_[kMdoc1MaxSHABlocks];
89 std::vector<std::vector<ShaBlockWitness>> attr_sha_;
90 std::vector<std::vector<v8>> attrb_;
92 std::vector<CborIndex> attr_mso_;
93 std::vector<AttrShift> attr_ei_;
94 std::vector<AttrShift> attr_ev_;
96 std::vector<v8> incb_;
97 std::vector<typename Cbor::position_witness> pwcb_;
98 typename Cbor::global_witness gwcb_;
100 vind prepad_, mso_len_;
102 CborIndex valid_, valid_from_, valid_until_;
103 CborIndex dev_key_info_, dev_key_, dev_key_pkx_, dev_key_pky_;
106 explicit Witness(
size_t num_attr)
107 : num_attr_(num_attr),
113 incb_(kMdoc1MaxMsoLen),
114 pwcb_(kMdoc1MaxMsoLen) {
115 for (
size_t i = 0; i < num_attr; ++i) {
116 attr_sha_[i].resize(2);
128 nb_ = lc.template vinput<8>();
131 for (
size_t i = 0; i + kCose1PrefixLen < 64 * kMdoc1MaxSHABlocks; ++i) {
132 in_[i] = lc.template vinput<8>();
135 for (
size_t j = 0; j < kMdoc1MaxSHABlocks; j++) {
136 sig_sha_[j].input(Q);
141 prepad_ = lc.template vinput<kMdoc1CborIndexBits>();
142 mso_len_ = lc.template vinput<kMdoc1CborIndexBits>();
143 for (
size_t i = 0; i < kMdoc1MaxMsoLen; ++i) {
144 pwcb_[i].encoded_sel_header = Q.input();
146 gwcb_.invprod_decode = Q.input();
147 gwcb_.cc0 = Q.input();
148 gwcb_.invprod_parse = Q.input();
151 valid_from_.input(lc);
152 valid_until_.input(lc);
153 dev_key_info_.input(lc);
155 dev_key_pkx_.input(lc);
156 dev_key_pky_.input(lc);
157 value_digests_.input(lc);
161 for (
size_t ai = 0; ai < num_attr_; ++ai) {
162 for (
size_t i = 0; i < 64 * 2; ++i) {
163 attrb_[ai].push_back(lc.template vinput<8>());
165 for (
size_t j = 0; j < 2; j++) {
166 attr_sha_[ai][j].input(Q);
168 attr_mso_[ai].input(lc);
169 attr_ei_[ai].input(lc);
170 attr_ev_[ai].input(lc);
186 explicit mdoc_1f(
const LogicCircuit& lc,
const EC& ec,
const Nat& order)
187 : lc_(lc), ec_(ec), order_(order), sha_(lc), r_(lc), cbor_(lc) {}
189 void assert_credential(EltW pkX, EltW pkY, EltW hash_tr,
191 const v8 now[],
const Witness& vw)
const {
192 Ecdsa ecc(lc_, ec_, order_);
194 ecc.verify_signature3(pkX, pkY, vw.e_, vw.sig_);
195 ecc.verify_signature3(vw.dpkx_, vw.dpky_, hash_tr, vw.dpk_sig_);
197 sha_.assert_message_with_prefix(kMdoc1MaxSHABlocks, vw.nb_, vw.in_,
198 kCose1Prefix, kCose1PrefixLen, vw.sig_sha_);
200 assert_hash(vw.e_, vw);
203 const v8 zz = lc_.template vbit<8>(0);
204 std::vector<v8> cmp_buf(kMdoc1MaxMsoLen);
210 std::vector<v8> in_cb(kMdoc1MaxMsoLen);
211 r_.unshift(vw.prepad_, kMdoc1MaxMsoLen, in_cb.data(),
212 kMdoc1MaxMsoLen - 5 - 2, vw.in_ + 5 + 2, zz, 3);
214 std::vector<typename Cbor::decode> dsC(kMdoc1MaxMsoLen);
215 std::vector<typename Cbor::parse_output> psC(kMdoc1MaxMsoLen);
216 cbor_.decode_and_assert_decode_and_parse(kMdoc1MaxMsoLen, dsC.data(),
217 psC.data(), in_cb.data(),
218 vw.pwcb_.data(), vw.gwcb_);
220 cbor_.assert_input_starts_at(kMdoc1MaxMsoLen, vw.prepad_, vw.mso_len_,
224 PathEntry vk[2] = {{vw.valid_, kValidityInfoLen, kValidityInfoID},
225 {vw.valid_from_, kValidFromLen, kValidFromID}};
226 assert_path(2, vk, vw, dsC, psC);
227 cbor_.assert_date_before_at(kMdoc1MaxMsoLen, vw.valid_from_.v, now,
231 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.valid_.v, 1, vw.valid_until_.k,
232 vw.valid_until_.v, vw.valid_until_.ndx, dsC.data(),
234 cbor_.assert_text_at(kMdoc1MaxMsoLen, vw.valid_until_.k, kValidUntilLen,
235 kValidUntilID, dsC.data());
236 cbor_.assert_date_after_at(kMdoc1MaxMsoLen, vw.valid_until_.v, now,
239 PathEntry dk[2] = {{vw.dev_key_info_, kDeviceKeyInfoLen, kDeviceKeyInfoID},
240 {vw.dev_key_, kDeviceKeyLen, kDeviceKeyID}};
241 assert_path(2, dk, vw, dsC, psC);
242 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.dev_key_.v, 2, vw.dev_key_pkx_.k,
243 vw.dev_key_pkx_.v, vw.dev_key_pkx_.ndx, dsC.data(),
245 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.dev_key_.v, 2, vw.dev_key_pky_.k,
246 vw.dev_key_pky_.v, vw.dev_key_pky_.ndx, dsC.data(),
248 cbor_.assert_negative_at(kMdoc1MaxMsoLen, vw.dev_key_pkx_.k, 1, dsC.data());
249 cbor_.assert_negative_at(kMdoc1MaxMsoLen, vw.dev_key_pky_.k, 2, dsC.data());
250 cbor_.assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.dev_key_pkx_.v, 32,
251 vw.dpkx_, dsC.data());
252 cbor_.assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.dev_key_pky_.v, 32,
253 vw.dpky_, dsC.data());
255 PathEntry ak[2] = {{vw.value_digests_, kValueDigestsLen, kValueDigestsID},
256 {vw.org_, kOrgLen, kOrgID}};
257 assert_path(2, ak, vw, dsC, psC);
260 for (
size_t ai = 0; ai < vw.num_attr_; ++ai) {
261 auto two = lc_.template vbit<8>(2);
263 sha_.assert_message(2, two, vw.attrb_[ai].data(),
264 vw.attr_sha_[ai].data());
266 EltW h = repack32(vw.attr_sha_[ai][1].h1);
268 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.org_.v, 2, vw.attr_mso_[ai].k,
269 vw.attr_mso_[ai].v, vw.attr_mso_[ai].ndx,
270 dsC.data(), psC.data());
271 cbor_.assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.attr_mso_[ai].v, 32,
275 r_.shift(vw.attr_ei_[ai].offset, 96, B, 128, vw.attrb_[ai].data(), zz, 3);
276 assert_attribute(96, vw.attr_ei_[ai].len, B, oa[ai].attr);
281 EltW repack32(
const sha_packed_v32 H[])
const {
282 EltW h = lc_.konst(0);
283 Elt twok = lc_.one();
284 for (
size_t j = 8; j-- > 0;) {
285 auto hj = sha_.bp_.unpack_v32(H[j]);
286 for (
size_t k = 0; k < 32; ++k) {
287 h = lc_.axpy(&h, twok, lc_.eval(hj[k]));
288 lc_.f_.add(twok, twok);
299 void assert_hash(
const EltW& e,
const Witness& vw)
const {
301 for (
size_t b = 0; b < kMdoc1MaxSHABlocks; ++b) {
302 auto bt = lc_.veq(vw.nb_, b + 1);
303 auto ebt = lc_.eval(bt);
304 for (
size_t i = 0; i < 8; ++i) {
305 for (
size_t k = 0; k < sha_.bp_.kNv32Elts; ++k) {
307 x[i][k] = lc_.mul(&ebt, vw.sig_sha_[b].h1[i][k]);
309 auto maybe_sha = lc_.mul(&ebt, vw.sig_sha_[b].h1[i][k]);
310 x[i][k] = lc_.add(&x[i][k], maybe_sha);
316 EltW h = repack32(x);
317 lc_.assert_eq(&h, e);
322 void assert_attribute(
size_t max,
const vind& len,
const v8 got[],
323 const v8 want[])
const {
325 for (
size_t j = 0; j < max; ++j) {
326 auto ll = lc_.vlt(j, len);
327 auto same = lc_.eq(8, got[j].data(), want[j].data());
328 lc_.assert_implies(&ll, same);
333 std::vector<typename Cbor::decode>& dsC,
334 std::vector<typename Cbor::parse_output>& psC)
const {
335 vind start = vw.prepad_;
336 for (
size_t i = 0; i < len; ++i) {
337 cbor_.assert_map_entry(kMdoc1MaxMsoLen, start, i, p[i].ind.k, p[i].ind.v,
338 p[i].ind.ndx, dsC.data(), psC.data());
339 cbor_.assert_text_at(kMdoc1MaxMsoLen, p[i].ind.k, p[i].l, p[i].name,