88 CborIndex valid_, valid_from_, valid_until_;
89 CborIndex dev_key_info_, dev_key_, dev_key_pkx_, dev_key_pky_;
91 std::vector<FullAttribute> attributes_;
92 std::vector<uint8_t> doc_type_;
95 std::vector<uint8_t> tagged_mso_bytes_;
110 bool parse_device_response(
size_t len,
const uint8_t resp[]) {
115 bool ok = root.decode(resp, len, np, 0);
117 log(ERROR,
"Failed to decode root");
122 auto docs = root.lookup(resp, 9, (uint8_t*)
"documents", di);
123 if (docs ==
nullptr)
return false;
126 auto docs0 = docs[1].index(0);
127 if (docs0 ==
nullptr)
return false;
129 auto dt = docs0[0].lookup(resp, 7, (uint8_t*)
"docType", di);
130 if (dt ==
nullptr)
return false;
131 doc_type_.insert(doc_type_.begin(), resp + dt[1].u_.string.pos,
132 resp + dt[1].u_.string.pos + dt[1].u_.string.len);
135 auto is = docs0[0].lookup(resp, 12, (uint8_t*)
"issuerSigned", di);
136 if (is ==
nullptr)
return false;
138 auto ia = is[1].lookup(resp, 10, (uint8_t*)
"issuerAuth", di);
139 if (ia ==
nullptr)
return false;
141 auto tmso = ia[1].index(2);
142 if (tmso ==
nullptr)
return false;
143 copy_header(t_mso_, tmso);
144 auto nsig = ia[1].index(3);
145 if (nsig ==
nullptr)
return false;
146 copy_header(sig_, nsig);
148 auto ns = is[1].lookup(resp, 10, (uint8_t*)
"nameSpaces", di);
149 if (ns ==
nullptr)
return false;
152 for (
const char* sn : kSupportedNamespaces) {
153 auto mldns = ns[1].lookup(resp, strlen(sn), (
const uint8_t*)sn, di);
154 if (mldns ==
nullptr)
continue;
156 auto tattr = mldns[1].index(ai++);
157 while (tattr !=
nullptr) {
160 size_t pos = tattr->children_[0].u_.string.pos;
161 size_t end = pos + tattr->children_[0].u_.string.len;
162 if (!er.decode(resp, end, pos, 0)) {
166 auto ei = er.lookup(resp, 17, (uint8_t*)
"elementIdentifier", di);
167 if (ei ==
nullptr)
return false;
168 auto ev = er.lookup(resp, 12, (uint8_t*)
"elementValue", di);
169 if (ev ==
nullptr)
return false;
170 auto digid = er.lookup(resp, 8, (uint8_t*)
"digestID", di);
171 if (digid ==
nullptr)
return false;
179 static_cast<size_t>(digid[1].u_.u64),
182 tattr->children_[0].u_.string.len +
186 tattr = mldns[1].index(ai++);
190 auto ds = docs0[0].lookup(resp, 12, (uint8_t*)
"deviceSigned", di);
191 if (ds ==
nullptr)
return false;
192 auto da = ds[1].lookup(resp, 10, (uint8_t*)
"deviceAuth", di);
193 if (da ==
nullptr)
return false;
194 auto dsi = da[1].lookup(resp, 15, (uint8_t*)
"deviceSignature", di);
195 if (dsi ==
nullptr)
return false;
196 auto ndksig = dsi[1].index(3);
197 if (ndksig ==
nullptr)
return false;
198 copy_header(dksig_, ndksig);
201 const uint8_t* pmso = resp + tmso->u_.string.pos + 5;
204 if (!mso.decode(pmso, tmso->u_.string.len - 5, pos, 0))
return false;
205 auto nv = mso.lookup(pmso, kValidityInfoLen, kValidityInfoID, valid_.ndx);
206 if (nv ==
nullptr)
return false;
207 copy_kv_header(valid_, nv);
209 auto nvf = nv[1].lookup(pmso, kValidFromLen, kValidFromID, valid_from_.ndx);
210 if (nvf ==
nullptr)
return false;
211 copy_kv_header(valid_from_, nvf);
214 nv[1].lookup(pmso, kValidUntilLen, kValidUntilID, valid_until_.ndx);
215 if (nvu ==
nullptr)
return false;
216 copy_kv_header(valid_until_, nvu);
218 auto ndki = mso.lookup(pmso, kDeviceKeyInfoLen, kDeviceKeyInfoID,
220 if (ndki ==
nullptr)
return false;
221 copy_kv_header(dev_key_info_, ndki);
223 auto ndk = ndki[1].lookup(pmso, kDeviceKeyLen, kDeviceKeyID, dev_key_.ndx);
224 if (ndk ==
nullptr)
return false;
225 copy_kv_header(dev_key_, ndk);
227 auto npkx = ndk[1].lookup_negative(-1, dev_key_pkx_.ndx);
228 if (npkx ==
nullptr)
return false;
229 copy_kv_header(dev_key_pkx_, npkx);
231 auto npky = ndk[1].lookup_negative(-2, dev_key_pky_.ndx);
232 if (npky ==
nullptr)
return false;
233 copy_kv_header(dev_key_pky_, npky);
236 mso.lookup(pmso, kValueDigestsLen, kValueDigestsID, value_digests_.ndx);
237 if (nvd ==
nullptr)
return false;
238 copy_kv_header(value_digests_, nvd);
243 auto norg = nvd[1].lookup(pmso, kOrgLen, kOrgID, org_.ndx);
244 if (norg !=
nullptr) {
245 copy_kv_header(org_, norg);
248 for (
auto& attr : attributes_) {
250 auto nss = nvd[1].lookup(pmso, strlen((
const char*)attr.mdl_ns),
252 if (nss ==
nullptr)
return false;
253 uint64_t hi = (uint64_t)attr.digest_id;
254 auto hattr = nss[1].lookup_unsigned(hi, attr.mso.ndx);
255 if (hattr ==
nullptr)
return false;
256 copy_kv_header(attr.mso, hattr);
259 tagged_mso_bytes_.assign(std::begin(kCose1Prefix), std::end(kCose1Prefix));
261 tagged_mso_bytes_.push_back((t_mso_.len >> 8) & 0xff);
262 tagged_mso_bytes_.push_back(t_mso_.len & 0xff);
263 for (
size_t i = 0; i < t_mso_.len; ++i) {
264 tagged_mso_bytes_.push_back(resp[t_mso_.pos + i]);
273 ind.k = n[0].header_pos_;
274 ind.v = n[1].header_pos_;
276 if (n[1].t_ == TEXT || n[1].t_ == BYTES) {
277 ind.pos = n[1].u_.string.pos;
278 ind.len = n[1].u_.string.len;
284 ind.k = n->header_pos_;
285 ind.pos = n->u_.string.pos;
286 ind.len = n->u_.string.len;
477class MdocSignatureWitness {
478 using Field =
typename EC::Field;
480 using Nat =
typename Field::N;
490 EcdsaWitness ew_, dkw_;
491 MacWitnessF macs_[3];
493 explicit MdocSignatureWitness(
const EC& ec,
const ScalarField& Fn,
499 macs_{MacWitnessF(ec.f_, gf_), MacWitnessF(ec.f_, gf_),
500 MacWitnessF(ec.f_, gf_)} {}
503 filler.push_back(e_);
504 filler.push_back(dpkx_);
505 filler.push_back(dpky_);
507 ew_.fill_witness(filler);
508 dkw_.fill_witness(filler);
509 for (
auto& mac : macs_) {
510 mac.fill_witness(filler);
514 bool compute_witness(Elt pkX, Elt pkY,
const uint8_t mdoc[],
515 size_t len,
const uint8_t transcript[],
519 if (!pm.parse_device_response(len, mdoc)) {
523 Nat ne = nat_from_hash<Nat>(pm.tagged_mso_bytes_.data(),
524 pm.tagged_mso_bytes_.size());
525 e_ = ec_.f_.to_montgomery(ne);
528 const size_t l = pm.sig_.len;
529 Nat nr = nat_from_be<Nat>(&mdoc[pm.sig_.pos]);
530 Nat ns = nat_from_be<Nat>(&mdoc[pm.sig_.pos + l / 2]);
531 ew_.compute_witness(pkX, pkY, ne, nr, ns);
533 Nat ne2 = compute_transcript_hash<Nat>(transcript, tlen, &pm.doc_type_);
534 const size_t l2 = pm.dksig_.len;
535 Nat nr2 = nat_from_be<Nat>(&mdoc[pm.dksig_.pos]);
536 Nat ns2 = nat_from_be<Nat>(&mdoc[pm.dksig_.pos + l2 / 2]);
537 size_t pmso = pm.t_mso_.pos + 5;
538 dpkx_ = ec_.f_.to_montgomery(
539 nat_from_be<Nat>(&mdoc[pmso + pm.dev_key_pkx_.pos]));
540 dpky_ = ec_.f_.to_montgomery(
541 nat_from_be<Nat>(&mdoc[pmso + pm.dev_key_pky_.pos]));
542 e2_ = ec_.f_.to_montgomery(ne2);
543 dkw_.compute_witness(dpkx_, dpky_, ne2, nr2, ns2);
552class MdocHashWitness {
553 using ECField =
typename EC::Field;
554 using ECElt =
typename ECField::Elt;
555 using ECNat =
typename ECField::N;
557 using vindex = std::array<Elt, kCborIndexBits>;
565 uint8_t signed_bytes_[kMaxSHABlocks * 64];
569 std::vector<std::vector<uint8_t>> attr_bytes_;
570 std::vector<std::vector<FlatSHA256Witness::BlockWitness>> atw_;
572 std::vector<uint8_t> attr_n_;
573 std::vector<CborIndex> attr_mso_;
574 std::vector<AttrShift> attr_ei_;
575 std::vector<AttrShift> attr_ev_;
583 explicit MdocHashWitness(
size_t num_attr,
const EC& ec,
const Field& Fn)
584 : ec_(ec), fn_(Fn), num_attr_(num_attr) {}
587 df.push_back(ind.k, kCborIndexBits, fn_);
591 df.push_back(attr.offset, kCborIndexBits, fn_);
592 df.push_back(attr.len, kCborIndexBits, fn_);
598 for (
size_t k = 0; k < 48; ++k) {
599 filler.push_back(BPENC.mkpacked_v32(bw.outw[k]));
601 for (
size_t k = 0; k < 64; ++k) {
602 filler.push_back(BPENC.mkpacked_v32(bw.oute[k]));
603 filler.push_back(BPENC.mkpacked_v32(bw.outa[k]));
605 for (
size_t k = 0; k < 8; ++k) {
606 filler.push_back(BPENC.mkpacked_v32(bw.h1[k]));
612 filler.push_back(numb_, 8, fn_);
614 for (
size_t i = kCose1PrefixLen; i < kMaxSHABlocks * 64; ++i) {
615 filler.push_back(signed_bytes_[i], 8, fn_);
617 for (
size_t j = 0; j < kMaxSHABlocks; j++) {
618 fill_sha(filler, bw_[j]);
622 fill_cbor_index(filler, pm_.valid_from_);
623 fill_cbor_index(filler, pm_.valid_until_);
624 fill_cbor_index(filler, pm_.dev_key_info_);
625 fill_cbor_index(filler, pm_.value_digests_);
628 for (
size_t ai = 0; ai < num_attr_; ++ai) {
629 for (
size_t i = 0; i < 2 * 64; ++i) {
630 filler.push_back(attr_bytes_[ai][i], 8, fn_);
632 for (
size_t j = 0; j < 2; j++) {
633 fill_sha(filler, atw_[ai][j]);
638 filler.push_back(attr_mso_[ai].v, kCborIndexBits, fn_);
639 fill_attr_shift(filler, attr_ei_[ai]);
640 fill_attr_shift(filler, attr_ev_[ai]);
644 bool compute_witness(
const uint8_t mdoc[],
size_t len,
645 const uint8_t transcript[],
size_t tlen,
647 const uint8_t tnow[],
size_t version) {
648 if (!pm_.parse_device_response(len, mdoc)) {
649 log(ERROR,
"Failed to parse device response");
653 std::vector<uint8_t> buf;
654 if (pm_.t_mso_.len >= kMaxSHABlocks * 64 - 9 - kCose1PrefixLen) {
655 log(ERROR,
"tagged mso is too big: %zu", pm_.t_mso_.len);
659 buf.assign(std::begin(kCose1Prefix), std::end(kCose1Prefix));
661 buf.push_back((pm_.t_mso_.len >> 8) & 0xff);
662 buf.push_back(pm_.t_mso_.len & 0xff);
663 for (
size_t i = 0; i < pm_.t_mso_.len; ++i) {
664 buf.push_back(mdoc[pm_.t_mso_.pos + i]);
667 FlatSHA256Witness::transform_and_witness_message(
668 buf.size(), buf.data(), kMaxSHABlocks, numb_, signed_bytes_, bw_);
670 ECNat ne = nat_from_u32<ECNat>(bw_[numb_ - 1].h1);
671 e_ = ec_.f_.to_montgomery(ne);
673 memcpy(now_, tnow, 20);
675 size_t pmso = pm_.t_mso_.pos + 5;
676 dpkx_ = ec_.f_.to_montgomery(
677 nat_from_be<ECNat>(&mdoc[pmso + pm_.dev_key_pkx_.pos]));
678 dpky_ = ec_.f_.to_montgomery(
679 nat_from_be<ECNat>(&mdoc[pmso + pm_.dev_key_pky_.pos]));
682 attr_n_.resize(attrs_len);
683 attr_mso_.resize(attrs_len);
684 attr_ev_.resize(attrs_len);
685 attr_ei_.resize(attrs_len);
686 attr_bytes_.resize(attrs_len);
687 atw_.resize(attrs_len);
690 for (
size_t i = 0; i < attrs_len; ++i) {
691 attr_bytes_[i].resize(128);
694 for (
auto fa : pm_.attributes_) {
695 if (fa == attrs[i]) {
696 FlatSHA256Witness::transform_and_witness_message(
697 fa.tag_len, &fa.doc[fa.tag_ind], 2, attr_n_[i],
698 &attr_bytes_[i][0], &atw_[i][0]);
699 attr_mso_[i] = fa.mso;
700 attr_ei_[i].offset = fa.id_ind - fa.tag_ind;
705 attr_ei_[i].offset -= 1;
706 if (fa.id_len > 23) {
707 attr_ei_[i].offset -= 1;
710 attr_ei_[i].len = fa.witness_length(attrs[i]);
711 attr_ev_[i].offset = fa.val_ind - fa.tag_ind;
712 attr_ev_[i].len = fa.val_len;
718 log(ERROR,
"Could not find attribute %.*s", attrs[i].id_len,