diff --git a/lib/circuits/mdoc/mdoc_attribute_ids.h b/lib/circuits/mdoc/mdoc_attribute_ids.h index d47bac4d..f75d6c8b 100644 --- a/lib/circuits/mdoc/mdoc_attribute_ids.h +++ b/lib/circuits/mdoc/mdoc_attribute_ids.h @@ -29,20 +29,21 @@ constexpr const char* kAAMVANamespace = "org.iso.18013.5.1.aamva"; constexpr const char* kEUAVNamespace = "eu.europa.ec.av.1"; constexpr const char* kEUDIPIDNamespace = "eu.europa.ec.eudi.pid.1"; constexpr const char* kISO23220Namespace = "org.iso.23220.1"; -constexpr const char* kISO23220PhotoIDNamespace = - "org.iso.23220.photoID.1"; +constexpr const char* kISO23220PhotoIDNamespace = "org.iso.23220.photoID.1"; constexpr const char* kISO23220DTCNamespace = "org.iso.23220.dtc.1"; +constexpr const char* kAadhaarNamespace = "in.gov.uidai.aadhaar.1"; constexpr const char* kSupportedNamespaces[] = { - kMDLNamespace, kAAMVANamespace, kEUAVNamespace, - kEUDIPIDNamespace, kISO23220Namespace, kISO23220PhotoIDNamespace, - kISO23220DTCNamespace}; + kMDLNamespace, kAAMVANamespace, kEUAVNamespace, + kEUDIPIDNamespace, kISO23220Namespace, kISO23220PhotoIDNamespace, + kISO23220DTCNamespace, kAadhaarNamespace}; constexpr const char* kIDPassDocType = "com.google.wallet.idcard.1"; constexpr const char* kMDLDocType = "org.iso.18013.5.1.mDL"; constexpr const char* kEUAVDocType = "eu.europa.ec.av.1"; constexpr const char* kEUDIPIDDocType = "eu.europa.ec.eudi.pid.1"; constexpr const char* kISO23220PhotoIDDocType = "org.iso.23220.photoID.1"; +constexpr const char* kAadhaarDocType = "in.gov.uidai.aadhaar.1"; // Extracted from // https://github.com/ISOWG10/ISO-18013/blob/main/Working%20Documents/Working%20Draft%20WG%2010_N2549_ISO-IEC%2018013-5-%20Personal%20identification%20%E2%80%94%20ISO-compliant%20driving%20licence%20%E2%80%94%20Part%205-%20Mobile%20driving%20lic.pdf @@ -261,6 +262,48 @@ constexpr MdocAttribute kMdocAttributes[] = { {"age_over_65", kEUAVNamespace}, {"age_over_67", kEUAVNamespace}, {"portrait", kEUAVNamespace}, + + // Aadhaar attributes + {"credential_issuing_date", kAadhaarNamespace}, + {"enrolment_date", kAadhaarNamespace}, + {"enrolment_number", kAadhaarNamespace}, + {"is_nri", kAadhaarNamespace}, + {"resident_image", kAadhaarNamespace}, + {"resident_name", kAadhaarNamespace}, + {"local_resident_name", kAadhaarNamespace}, + {"age_above18", kAadhaarNamespace}, + {"age_above60", kAadhaarNamespace}, + {"age_above75", kAadhaarNamespace}, + {"dob", kAadhaarNamespace}, + {"gender", kAadhaarNamespace}, + {"building", kAadhaarNamespace}, + {"local_building", kAadhaarNamespace}, + {"locality", kAadhaarNamespace}, + {"local_locality", kAadhaarNamespace}, + {"street", kAadhaarNamespace}, + {"local_street", kAadhaarNamespace}, + {"landmark", kAadhaarNamespace}, + {"local_landmark", kAadhaarNamespace}, + {"vtc", kAadhaarNamespace}, + {"local_vtc", kAadhaarNamespace}, + {"sub_district", kAadhaarNamespace}, + {"local_sub_district", kAadhaarNamespace}, + {"district", kAadhaarNamespace}, + {"local_district", kAadhaarNamespace}, + {"state", kAadhaarNamespace}, + {"local_state", kAadhaarNamespace}, + {"po_name", kAadhaarNamespace}, + {"local_po_name", kAadhaarNamespace}, + {"pincode", kAadhaarNamespace}, + {"address", kAadhaarNamespace}, + {"local_address", kAadhaarNamespace}, + {"mobile", kAadhaarNamespace}, + {"masked_mobile", kAadhaarNamespace}, + {"email", kAadhaarNamespace}, + {"masked_email", kAadhaarNamespace}, + {"masked_uid", kAadhaarNamespace}, + {"aadhaar_type", kAadhaarNamespace}, + {"expires_on", kAadhaarNamespace}, }; } // namespace proofs diff --git a/lib/gf2k/sysdep.h b/lib/gf2k/sysdep.h index 6192ca59..6b0ba6bc 100644 --- a/lib/gf2k/sysdep.h +++ b/lib/gf2k/sysdep.h @@ -84,7 +84,7 @@ static inline std::array uint64x2_of_gf2_128(gf2_128_elt_t x) { } static inline gf2_128_elt_t gf2_128_of_uint64x2( - const std::array &x) { + const std::array& x) { return gf2_128_elt_t{static_cast(x[0]), static_cast(x[1])}; } @@ -137,7 +137,7 @@ static inline std::array uint64x2_of_gf2_128(gf2_128_elt_t x) { } static inline gf2_128_elt_t gf2_128_of_uint64x2( - const std::array &x) { + const std::array& x) { return gf2_128_elt_t{static_cast(x[0]), static_cast(x[1])}; } @@ -247,7 +247,83 @@ static inline gf2_128_elt_t gf2_128_mul(gf2_128_elt_t x, gf2_128_elt_t y) { } // namespace proofs #else -#error "unimplemented gf2k/sysdep.h" + +// Generic implementation assuming a 64x64->64 integer multiplier. +struct gf2_128_elt_t { + uint64_t l[2]; +}; + +static inline std::array uint64x2_of_gf2_128(gf2_128_elt_t x) { + return std::array{x.l[0], x.l[1]}; +} + +static inline gf2_128_elt_t gf2_128_of_uint64x2( + const std::array& x) { + return gf2_128_elt_t{x[0], x[1]}; +} + +static inline gf2_128_elt_t gf2_128_add(gf2_128_elt_t x, gf2_128_elt_t y) { + return gf2_128_elt_t{x.l[0] ^ y.l[0], x.l[1] ^ y.l[1]}; +} + +// 64x64->64 bit GF(2)[X] multiplication via Kronecker +// substitution. Modeled after the Highway library +// https://github.com/google/highway/blob/master/hwy/ops/generic_ops-inl.h +// and the ghash implementation in BearSSL. +static inline uint64_t clmul64_lo(uint64_t x, uint64_t y) { + uint64_t m0 = 0x1111111111111111ull, m1 = 0x2222222222222222ull, + m2 = 0x4444444444444444ull, m3 = 0x8888888888888888ull; + uint64_t x0 = x & m0, x1 = x & m1, x2 = x & m2, x3 = x & m3; + uint64_t y0 = y & m0, y1 = y & m1, y2 = y & m2, y3 = y & m3; + uint64_t z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); + uint64_t z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); + uint64_t z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); + uint64_t z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); + return (z0 & m0) | (z1 & m1) | (z2 & m2) | (z3 & m3); +} + +static inline uint64_t bitrev64(uint64_t n) { + n = ((n >> 1) & 0x5555555555555555ull) | ((n & 0x5555555555555555ull) << 1); + n = ((n >> 2) & 0x3333333333333333ull) | ((n & 0x3333333333333333ull) << 2); + n = ((n >> 4) & 0x0f0f0f0f0f0f0f0full) | ((n & 0x0f0f0f0f0f0f0f0full) << 4); + n = ((n >> 8) & 0x00ff00ff00ff00ffull) | ((n & 0x00ff00ff00ff00ffull) << 8); + n = ((n >> 16) & 0x0000ffff0000ffffull) | ((n & 0x0000ffff0000ffffull) << 16); + return (n << 32) | (n >> 32); +} + +static inline uint64_t clmul64_hi(uint64_t x, uint64_t y) { + return bitrev64(clmul64_lo(bitrev64(x), bitrev64(y))) >> 1; +} + +// 64x64 -> 128 +static inline gf2_128_elt_t clmul64(uint64_t x, uint64_t y) { + return gf2_128_elt_t{clmul64_lo(x, y), clmul64_hi(x, y)}; +} + +// return (t0 + x^64 * t1) +static inline gf2_128_elt_t gf2_128_reduce(gf2_128_elt_t t0, gf2_128_elt_t t1) { + uint64_t a = t1.l[1]; + t0.l[0] ^= a; + t0.l[0] ^= a << 1; + t0.l[1] ^= a >> 63; + t0.l[0] ^= a << 2; + t0.l[1] ^= a >> 62; + t0.l[0] ^= a << 7; + t0.l[1] ^= a >> 57; + t0.l[1] ^= t1.l[0]; + return t0; +} +static inline gf2_128_elt_t gf2_128_mul(gf2_128_elt_t x, gf2_128_elt_t y) { + // karatsuba + gf2_128_elt_t t0 = clmul64(x.l[0], y.l[0]); + gf2_128_elt_t t2 = clmul64(x.l[1], y.l[1]); + gf2_128_elt_t t1 = clmul64(x.l[0] ^ x.l[1], y.l[0] ^ y.l[1]); + t1 = gf2_128_add(t1, gf2_128_add(t0, t2)); + t1 = gf2_128_reduce(t1, t2); + t0 = gf2_128_reduce(t0, t1); + return t0; +} + #endif #endif // PRIVACY_PROOFS_ZK_LIB_GF2K_SYSDEP_H_