45 using v8 =
typename LogicCircuit::v8;
46 using v32 =
typename LogicCircuit::v32;
47 using v256 =
typename LogicCircuit::v256;
49 using vind =
typename LogicCircuit::template bitvec<kCborIndexBits>;
53 using ShaBlockWitness =
typename Flatsha::BlockWitness;
54 using sha_packed_v32 =
typename Flatsha::packed_v32;
65 void input(
const LogicCircuit& lc) {
66 k = lc.template vinput<kCborIndexBits>();
73 void input(
const LogicCircuit& lc) {
74 offset = lc.template vinput<kCborIndexBits>();
75 len = lc.template vinput<kCborIndexBits>();
81 v8 in_[64 * kMaxSHABlocks];
84 ShaBlockWitness sig_sha_[kMaxSHABlocks];
86 std::vector<std::vector<ShaBlockWitness>> attr_sha_;
87 std::vector<std::vector<v8>> attrb_;
92 std::vector<CborIndex> attr_mso_;
93 std::vector<AttrShift> attr_ei_;
94 std::vector<AttrShift> attr_ev_;
97 explicit Witness(
size_t num_attr) {
99 attr_mso_.resize(num_attr);
100 attr_ei_.resize(num_attr);
101 attr_ev_.resize(num_attr);
102 attr_sha_.resize(num_attr);
103 for (
size_t i = 0; i < num_attr; ++i) {
104 attr_sha_[i].resize(2);
107 attrb_.resize(num_attr);
111 nb_ = lc.template vinput<8>();
114 for (
size_t i = 0; i + kCose1PrefixLen < 64 * kMaxSHABlocks; ++i) {
115 in_[i] = lc.template vinput<8>();
117 for (
size_t j = 0; j < kMaxSHABlocks; j++) {
118 sig_sha_[j].input(Q);
121 valid_from_.input(lc);
122 valid_until_.input(lc);
123 dev_key_info_.input(lc);
124 value_digests_.input(lc);
127 for (
size_t ai = 0; ai < num_attr_; ++ai) {
128 for (
size_t i = 0; i < 64 * 2; ++i) {
129 attrb_[ai].push_back(lc.template vinput<8>());
131 for (
size_t j = 0; j < 2; j++) {
132 attr_sha_[ai][j].input(Q);
134 attr_mso_[ai].input(lc);
135 attr_ei_[ai].input(lc);
136 attr_ev_[ai].input(lc);
141 explicit MdocHash(
const LogicCircuit& lc) : lc_(lc), sha_(lc), r_(lc) {}
144 const v8 now[],
const v256& e,
145 const v256& dpkx,
const v256& dpky,
146 const Witness& vw)
const {
147 sha_.assert_message_hash_with_prefix(kMaxSHABlocks, vw.nb_, vw.in_,
148 kCose1Prefix, kCose1PrefixLen, e,
152 const v8 zz = lc_.template vbit<8>(0);
153 std::vector<v8> cmp_buf(kMaxMsoLen);
161 r_.shift(vw.valid_from_.k, kValidFromLen + kDateLen, &cmp_buf[0],
162 kMaxMsoLen, vw.in_ + 5 + 2, zz, 3);
163 assert_bytes_at(kValidFromLen, &cmp_buf[0], kValidFromCheck);
164 auto cmp = CMP.leq(kDateLen, &cmp_buf[kValidFromLen], &now[0]);
168 r_.shift(vw.valid_until_.k, kValidUntilLen + kDateLen, &cmp_buf[0],
169 kMaxMsoLen, vw.in_ + 5 + 2, zz, 3);
170 assert_bytes_at(kValidUntilLen, &cmp_buf[0], kValidUntilCheck);
171 cmp = CMP.leq(kDateLen, &now[0], &cmp_buf[kValidUntilLen]);
175 r_.shift(vw.dev_key_info_.k, kDeviceKeyInfoLen + 3 + 32 + 32, &cmp_buf[0],
176 kMaxMsoLen, vw.in_ + 5 + 2, zz, 3);
177 assert_bytes_at(kDeviceKeyInfoLen, &cmp_buf[0], kDeviceKeyInfoCheck);
178 uint8_t dpkyCheck[] = {0x22, 0x58, 0x20};
179 assert_bytes_at(
sizeof(dpkyCheck), &cmp_buf[65], dpkyCheck);
181 assert_key(dpkx, &cmp_buf[kPkxInd]);
182 assert_key(dpky, &cmp_buf[kPkyInd]);
186 r_.shift(vw.value_digests_.k, kValueDigestsLen, cmp_buf.data(), kMaxMsoLen,
187 vw.in_ + 5 + 2, zz, 3);
188 assert_bytes_at(13, &cmp_buf[0], kValueDigestsCheck);
189 assert_bytes_at(18, &cmp_buf[14], &kValueDigestsCheck[14]);
192 for (
size_t ai = 0; ai < vw.num_attr_; ++ai) {
195 r_.shift(vw.attr_mso_[ai].k, 2 + 32, &cmp_buf[0], kMaxMsoLen,
196 vw.in_ + 5 + 2, zz, 3);
199 assert_bytes_at(2, &cmp_buf[0], kTag32);
203 for (
size_t j = 0; j < 256; ++j) {
204 mm[j] = cmp_buf[2 + (255 - j) / 8][(j % 8)];
207 auto two = lc_.template vbit<8>(2);
208 sha_.assert_message_hash(2, two, vw.attrb_[ai].data(), mm,
209 vw.attr_sha_[ai].data());
212 r_.shift(vw.attr_ei_[ai].offset, 96, B, 128, vw.attrb_[ai].data(), zz, 3);
213 assert_attribute(96, vw.attr_ei_[ai].len, B, oa[ai]);
218 void assert_bytes_at(
size_t len,
const v8 buf[],
219 const uint8_t want[])
const {
220 for (
size_t i = 0; i < len; ++i) {
221 auto want_i = lc_.template vbit<8>(want[i]);
222 lc_.vassert_eq(&buf[i], want_i);
228 void assert_attribute(
size_t max,
const vind& len,
const v8 got[],
232 for (
size_t j = 0; j < 32; ++j) {
233 want[j] = oa.attr[j];
235 for (
size_t j = 0; j < 64; ++j) {
236 want[32 + j] = oa.v1[j];
240 for (
size_t j = 0; j < max; ++j) {
241 auto ll = lc_.vlt(j, len);
242 auto same = lc_.eq(8, got[j].data(), want[j].data());
243 lc_.assert_implies(&ll, same);
248 void assert_key(v256 key,
const v8 buf_be[])
const {
250 for (
size_t i = 0; i < 256; ++i) {
251 m[i] = buf_be[31 - (i / 8)][i % 8];
253 lc_.vassert_eq(&m, key);
265 static constexpr uint8_t kValidFromCheck[] = {
266 0x69, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x46, 0x72, 0x6F, 0x6D, 0xC0, 0x74};
267 static constexpr size_t kValidFromLen =
sizeof(kValidFromCheck);
270 static constexpr uint8_t kValidUntilCheck[] = {0x6A, 0x76, 0x61, 0x6C, 0x69,
271 0x64, 0x55, 0x6E, 0x74, 0x69,
273 static constexpr size_t kValidUntilLen =
sizeof(kValidUntilCheck);
282 static constexpr uint8_t kDeviceKeyInfoCheck[] = {
283 0x6D, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4B, 0x65, 0x79, 0x49,
284 0x6E, 0x66, 0x6F, 0xA1, 0x69, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
285 0x4B, 0x65, 0x79, 0xA4, 0x01, 0x02, 0x20, 0x01, 0x21, 0x58, 0x20};
286 static constexpr size_t kDeviceKeyInfoLen =
sizeof(kDeviceKeyInfoCheck);
287 static constexpr size_t kPkxInd = kDeviceKeyInfoLen;
288 static constexpr size_t kPkyInd = 68;
292 static constexpr uint8_t kValueDigestsCheck[] = {
293 0x6C, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x44, 0x69, 0x67,
294 0x65, 0x73, 0x74, 0x73,
296 0x71, 0x6F, 0x72, 0x67, 0x2E, 0x69, 0x73, 0x6F, 0x2E,
297 0x31, 0x38, 0x30, 0x31, 0x33, 0x2E, 0x35, 0x2E, 0x31};
298 static constexpr size_t kValueDigestsLen =
sizeof(kValueDigestsCheck);
300 static constexpr size_t kDateLen = 20;
302 const LogicCircuit& lc_;
304 Routing<LogicCircuit> r_;