36 using EltW =
typename LogicCircuit::EltW;
37 using Elt =
typename LogicCircuit::Elt;
38 using Nat =
typename Field::N;
42 using v8 =
typename LogicCircuit::v8;
43 using v32 =
typename LogicCircuit::v32;
44 using v256 =
typename LogicCircuit::v256;
48 using Routing = Routing<LogicCircuit>;
49 using ShaBlockWitness =
typename Flatsha::BlockWitness;
50 using sha_packed_v32 =
typename Flatsha::packed_v32;
51 using Cbor = Cbor<LogicCircuit, kMdoc1CborIndexBits>;
52 using vind =
typename Cbor::vindex;
54 const LogicCircuit& lc_;
61 void input(
const LogicCircuit& lc) {
62 k = lc.template vinput<kMdoc1CborIndexBits>();
63 v = lc.template vinput<kMdoc1CborIndexBits>();
64 ndx = lc.template vinput<kMdoc1CborIndexBits>();
71 void input(
const LogicCircuit& lc) {
72 offset = lc.template vinput<kMdoc1CborIndexBits>();
73 len = lc.template vinput<kMdoc1CborIndexBits>();
83 EcdsaWitness dpk_sig_;
85 v8 in_[64 * kMdoc1MaxSHABlocks];
87 ShaBlockWitness sig_sha_[kMdoc1MaxSHABlocks];
91 std::vector<std::vector<ShaBlockWitness>> attr_sha_;
92 std::vector<std::vector<v8>> attrb_;
94 std::vector<CborIndex> attr_mso_;
95 std::vector<AttrShift> attr_ei_;
96 std::vector<AttrShift> attr_ev_;
98 std::vector<v8> incb_;
99 std::vector<typename Cbor::position_witness> pwcb_;
100 typename Cbor::global_witness gwcb_;
102 vind prepad_, mso_len_;
104 CborIndex valid_, valid_from_, valid_until_;
105 CborIndex dev_key_info_, dev_key_, dev_key_pkx_, dev_key_pky_;
108 explicit Witness(
size_t num_attr)
109 : num_attr_(num_attr),
115 incb_(kMdoc1MaxMsoLen),
116 pwcb_(kMdoc1MaxMsoLen) {
117 for (
size_t i = 0; i < num_attr; ++i) {
118 attr_sha_[i].resize(2);
123 const Counter<LogicCircuit> CTRC(lc);
132 nb_ = lc.template vinput<8>();
135 for (
size_t i = 0; i + kCose1PrefixLen < 64 * kMdoc1MaxSHABlocks; ++i) {
136 in_[i] = lc.template vinput<8>();
139 for (
size_t j = 0; j < kMdoc1MaxSHABlocks; j++) {
140 sig_sha_[j].input(Q);
145 prepad_ = lc.template vinput<kMdoc1CborIndexBits>();
146 mso_len_ = lc.template vinput<kMdoc1CborIndexBits>();
147 for (
size_t i = 0; i < kMdoc1MaxMsoLen; ++i) {
148 pwcb_[i].encoded_sel_header = Q.input();
150 gwcb_.invprod_decode = Q.input();
151 gwcb_.cc0_counter = CTRC.input();
152 gwcb_.invprod_parse = Q.input();
155 valid_from_.input(lc);
156 valid_until_.input(lc);
157 dev_key_info_.input(lc);
159 dev_key_pkx_.input(lc);
160 dev_key_pky_.input(lc);
161 value_digests_.input(lc);
165 for (
size_t ai = 0; ai < num_attr_; ++ai) {
166 for (
size_t i = 0; i < 64 * 2; ++i) {
167 attrb_[ai].push_back(lc.template vinput<8>());
169 for (
size_t j = 0; j < 2; j++) {
170 attr_sha_[ai][j].input(Q);
172 attr_mso_[ai].input(lc);
173 attr_ei_[ai].input(lc);
174 attr_ev_[ai].input(lc);
183 void input(
const LogicCircuit& lc) {
184 for (
size_t j = 0; j < 96; ++j) {
185 attr[j] = lc.template vinput<8>();
187 len = lc.template vinput<8>();
197 explicit mdoc_1f(
const LogicCircuit& lc,
const EC& ec,
const Nat& order)
198 : lc_(lc), ec_(ec), order_(order), sha_(lc), r_(lc), cbor_(lc) {}
200 void assert_credential(EltW pkX, EltW pkY, EltW hash_tr,
202 const v8 now[],
const Witness& vw)
const {
203 Ecdsa ecc(lc_, ec_, order_);
205 ecc.verify_signature3(pkX, pkY, vw.e_, vw.sig_);
206 ecc.verify_signature3(vw.dpkx_, vw.dpky_, hash_tr, vw.dpk_sig_);
208 sha_.assert_message_with_prefix(kMdoc1MaxSHABlocks, vw.nb_, vw.in_,
209 kCose1Prefix, kCose1PrefixLen, vw.sig_sha_);
211 assert_hash(vw.e_, vw);
214 const v8 zz = lc_.template vbit<8>(0);
215 std::vector<v8> cmp_buf(kMdoc1MaxMsoLen);
221 std::vector<v8> in_cb(kMdoc1MaxMsoLen);
222 r_.unshift(vw.prepad_, kMdoc1MaxMsoLen, in_cb.data(),
223 kMdoc1MaxMsoLen - 5 - 2, vw.in_ + 5 + 2, zz, 3);
225 std::vector<typename Cbor::decode> dsC(kMdoc1MaxMsoLen);
226 std::vector<typename Cbor::parse_output> psC(kMdoc1MaxMsoLen);
227 cbor_.decode_and_assert_decode_and_parse(kMdoc1MaxMsoLen, dsC.data(),
228 psC.data(), in_cb.data(),
229 vw.pwcb_.data(), vw.gwcb_);
231 cbor_.assert_input_starts_at(kMdoc1MaxMsoLen, vw.prepad_, vw.mso_len_,
235 PathEntry vk[2] = {{vw.valid_, kValidityInfoLen, kValidityInfoID},
236 {vw.valid_from_, kValidFromLen, kValidFromID}};
237 assert_path(2, vk, vw, dsC, psC);
238 cbor_.assert_date_before_at(kMdoc1MaxMsoLen, vw.valid_from_.v, now,
242 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.valid_.v, 1, vw.valid_until_.k,
243 vw.valid_until_.v, vw.valid_until_.ndx, dsC.data(),
245 cbor_.assert_text_at(kMdoc1MaxMsoLen, vw.valid_until_.k, kValidUntilLen,
246 kValidUntilID, dsC.data());
247 cbor_.assert_date_after_at(kMdoc1MaxMsoLen, vw.valid_until_.v, now,
250 PathEntry dk[2] = {{vw.dev_key_info_, kDeviceKeyInfoLen, kDeviceKeyInfoID},
251 {vw.dev_key_, kDeviceKeyLen, kDeviceKeyID}};
252 assert_path(2, dk, vw, dsC, psC);
253 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.dev_key_.v, 2, vw.dev_key_pkx_.k,
254 vw.dev_key_pkx_.v, vw.dev_key_pkx_.ndx, dsC.data(),
256 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.dev_key_.v, 2, vw.dev_key_pky_.k,
257 vw.dev_key_pky_.v, vw.dev_key_pky_.ndx, dsC.data(),
259 cbor_.assert_negative_at(kMdoc1MaxMsoLen, vw.dev_key_pkx_.k, 1, dsC.data());
260 cbor_.assert_negative_at(kMdoc1MaxMsoLen, vw.dev_key_pky_.k, 2, dsC.data());
261 assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.dev_key_pkx_.v, 32, vw.dpkx_,
263 assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.dev_key_pky_.v, 32, vw.dpky_,
266 PathEntry ak[2] = {{vw.value_digests_, kValueDigestsLen, kValueDigestsID},
267 {vw.org_, kOrgLen, kOrgID}};
268 assert_path(2, ak, vw, dsC, psC);
271 for (
size_t ai = 0; ai < vw.num_attr_; ++ai) {
272 auto two = lc_.template vbit<8>(2);
274 sha_.assert_message(2, two, vw.attrb_[ai].data(),
275 vw.attr_sha_[ai].data());
278 cbor_.assert_map_entry(kMdoc1MaxMsoLen, vw.org_.v, 2, vw.attr_mso_[ai].k,
279 vw.attr_mso_[ai].v, vw.attr_mso_[ai].ndx,
280 dsC.data(), psC.data());
281 EltW h = repack32(vw.attr_sha_[ai][1].h1);
282 assert_elt_as_be_bytes_at(kMdoc1MaxMsoLen, vw.attr_mso_[ai].v, 32, h,
286 r_.shift(vw.attr_ei_[ai].offset, 96, B, 128, vw.attrb_[ai].data(), zz, 3);
287 assert_attribute(96, oa[ai].len, B, oa[ai].attr);
295 EltW repack32(
const sha_packed_v32 H[])
const {
296 EltW h = lc_.konst(0);
297 Elt twok = lc_.one();
298 for (
size_t j = 8; j-- > 0;) {
299 auto hj = sha_.bp_.unpack_v32(H[j]);
300 for (
size_t k = 0; k < 32; ++k) {
301 h = lc_.axpy(&h, twok, lc_.eval(hj[k]));
302 lc_.f_.add(twok, twok);
313 void assert_hash(
const EltW& e,
const Witness& vw)
const {
315 for (
size_t b = 0; b < kMdoc1MaxSHABlocks; ++b) {
316 auto bt = lc_.veq(vw.nb_, b + 1);
317 auto ebt = lc_.eval(bt);
318 for (
size_t i = 0; i < 8; ++i) {
319 for (
size_t k = 0; k < sha_.bp_.kNv32Elts; ++k) {
321 x[i][k] = lc_.mul(&ebt, vw.sig_sha_[b].h1[i][k]);
323 auto maybe_sha = lc_.mul(&ebt, vw.sig_sha_[b].h1[i][k]);
324 x[i][k] = lc_.add(&x[i][k], maybe_sha);
330 EltW h = repack32(x);
331 lc_.assert_eq(&h, e);
336 void assert_attribute(
size_t max,
const v8& len,
const v8 got[],
337 const v8 want[])
const {
339 for (
size_t j = 0; j < max; ++j) {
340 auto ll = lc_.vlt(j, len);
341 auto same = lc_.eq(8, got[j].data(), want[j].data());
342 lc_.assert_implies(&ll, same);
347 std::vector<typename Cbor::decode>& dsC,
348 std::vector<typename Cbor::parse_output>& psC)
const {
349 vind start = vw.prepad_;
350 for (
size_t i = 0; i < len; ++i) {
351 cbor_.assert_map_entry(kMdoc1MaxMsoLen, start, i, p[i].ind.k, p[i].ind.v,
352 p[i].ind.ndx, dsC.data(), psC.data());
353 cbor_.assert_text_at(kMdoc1MaxMsoLen, p[i].ind.k, p[i].l, p[i].name,
359 void assert_elt_as_be_bytes_at(
size_t n,
const vind& j,
size_t len, EltW X,
360 const typename Cbor::decode ds[])
const {
361 const LogicCircuit& LC = lc_;
363 std::vector<EltW> A(n);
364 for (
size_t i = 0; i < n; ++i) {
365 A[i] = ds[i].bd.as_scalar;
367 EltW tx = LC.konst(0), k256 = LC.konst(256);
369 std::vector<EltW> B(2 + len);
372 r_.shift(j, len + 2, B.data(), n, A.data(), LC.konst(0), unroll);
374 size_t expected_header = (2 << 5) + len;
375 auto eh = LC.konst(expected_header);
376 LC.assert_eq(&B[0], eh);
377 }
else if (len < 256) {
378 size_t expected_header = (2 << 5) + 24;
379 auto eh = LC.konst(expected_header);
380 LC.assert_eq(&B[0], eh);
381 LC.assert_eq(&B[1], LC.konst(len));
384 check(
false,
"len >= 256");
387 for (
size_t i = 0; i < len; ++i) {
388 auto tmp = LC.mul(&tx, k256);
389 tx = LC.add(&tmp, B[i + si]);
392 LC.assert_eq(&tx, X);