types.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. #ifndef __OBLIVDS_TYPES_HPP__
  2. #define __OBLIVDS_TYPES_HPP__
  3. #include <tuple>
  4. #include <vector>
  5. #include <array>
  6. #include <cstdint>
  7. #include <x86intrin.h> // SSE and AVX intrinsics
  8. #include <bsd/stdlib.h> // arc4random_buf
  9. // The number of bits in an MPC secret-shared memory word
  10. #ifndef VALUE_BITS
  11. #define VALUE_BITS 64
  12. #endif
  13. // Values in MPC secret-shared memory are of this type.
  14. // This is the type of the underlying shared value, not the types of the
  15. // shares themselves.
  16. #if VALUE_BITS == 64
  17. using value_t = uint64_t;
  18. #elif VALUE_BITS == 32
  19. using value_t = uint32_t;
  20. #else
  21. #error "Unsupported value of VALUE_BITS"
  22. #endif
  23. // Secret-shared bits are of this type. Note that it is standards
  24. // compliant to treat a bool as an unsigned integer type with values 0
  25. // and 1.
  26. using bit_t = bool;
  27. // Counts of the number of bits in a value are of this type, which must
  28. // be large enough to store the _value_ VALUE_BITS
  29. using nbits_t = uint8_t;
  30. // Convert a number of bits to the number of bytes required to store (or
  31. // more to the point, send) them.
  32. #define BITBYTES(nbits) (((nbits)+7)>>3)
  33. // A mask of this many bits; the test is to prevent 1<<nbits from
  34. // overflowing if nbits == VALUE_BITS
  35. #define MASKBITS(nbits) (((nbits) < VALUE_BITS) ? (value_t(1)<<(nbits))-1 : ~0)
  36. // The type of a register holding an additive share of a value
  37. struct RegAS {
  38. value_t ashare;
  39. RegAS() : ashare(0) {}
  40. inline value_t share() const { return ashare; }
  41. inline void set(value_t s) { ashare = s; }
  42. // Set each side's share to a random value nbits bits long
  43. inline void randomize(size_t nbits = VALUE_BITS) {
  44. value_t mask = MASKBITS(nbits);
  45. arc4random_buf(&ashare, sizeof(ashare));
  46. ashare &= mask;
  47. }
  48. inline RegAS &operator+=(const RegAS &rhs) {
  49. this->ashare += rhs.ashare;
  50. return *this;
  51. }
  52. inline RegAS operator+(const RegAS &rhs) const {
  53. RegAS res = *this;
  54. res += rhs;
  55. return res;
  56. }
  57. inline RegAS &operator-=(const RegAS &rhs) {
  58. this->ashare -= rhs.ashare;
  59. return *this;
  60. }
  61. inline RegAS operator-(const RegAS &rhs) const {
  62. RegAS res = *this;
  63. res -= rhs;
  64. return res;
  65. }
  66. inline RegAS operator-() const {
  67. RegAS res = *this;
  68. res.ashare = -res.ashare;
  69. return res;
  70. }
  71. inline RegAS &operator*=(value_t rhs) {
  72. this->ashare *= rhs;
  73. return *this;
  74. }
  75. inline RegAS operator*(value_t rhs) const {
  76. RegAS res = *this;
  77. res *= rhs;
  78. return res;
  79. }
  80. // Multiply a scalar by a vector
  81. template <size_t N>
  82. inline std::array<RegAS,N> operator*(std::array<value_t,N> rhs) const {
  83. std::array<RegAS,N> res;
  84. for (size_t i=0;i<N;++i) {
  85. res[i] = *this;
  86. res[i] *= rhs[i];
  87. }
  88. return res;
  89. }
  90. inline RegAS &operator&=(value_t mask) {
  91. this->ashare &= mask;
  92. return *this;
  93. }
  94. inline RegAS operator&(value_t mask) const {
  95. RegAS res = *this;
  96. res &= mask;
  97. return res;
  98. }
  99. // Multiply by the local share of the argument, not multiplcation of
  100. // two shared values (two versions)
  101. inline RegAS &mulshareeq(const RegAS &rhs) {
  102. *this *= rhs.ashare;
  103. return *this;
  104. }
  105. inline RegAS mulshare(const RegAS &rhs) const {
  106. RegAS res = *this;
  107. res *= rhs.ashare;
  108. return res;
  109. }
  110. inline void dump() const {
  111. printf("%016lx", ashare);
  112. }
  113. };
  114. inline value_t combine(const RegAS &A, const RegAS &B,
  115. nbits_t nbits = VALUE_BITS) {
  116. value_t mask = ~0;
  117. if (nbits < VALUE_BITS) {
  118. mask = (value_t(1)<<nbits)-1;
  119. }
  120. return (A.ashare + B.ashare) & mask;
  121. }
  122. // The type of a register holding a bit share
  123. struct RegBS {
  124. bit_t bshare;
  125. RegBS() : bshare(0) {}
  126. inline bit_t share() const { return bshare; }
  127. inline void set(bit_t s) { bshare = s; }
  128. // Set each side's share to a random bit
  129. inline void randomize() {
  130. unsigned char randb;
  131. arc4random_buf(&randb, sizeof(randb));
  132. bshare = randb & 1;
  133. }
  134. inline RegBS &operator^=(const RegBS &rhs) {
  135. this->bshare ^= rhs.bshare;
  136. return *this;
  137. }
  138. inline RegBS operator^(const RegBS &rhs) const {
  139. RegBS res = *this;
  140. res ^= rhs;
  141. return res;
  142. }
  143. inline RegBS &operator^=(const bit_t &rhs) {
  144. this->bshare ^= rhs;
  145. return *this;
  146. }
  147. inline RegBS operator^(const bit_t &rhs) const {
  148. RegBS res = *this;
  149. res ^= rhs;
  150. return res;
  151. }
  152. };
  153. // The type of a register holding an XOR share of a value
  154. struct RegXS {
  155. value_t xshare;
  156. RegXS() : xshare(0) {}
  157. RegXS(const RegBS &b) { xshare = b.bshare ? ~0 : 0; }
  158. inline value_t share() const { return xshare; }
  159. inline void set(value_t s) { xshare = s; }
  160. // Set each side's share to a random value nbits bits long
  161. inline void randomize(size_t nbits = VALUE_BITS) {
  162. value_t mask = MASKBITS(nbits);
  163. arc4random_buf(&xshare, sizeof(xshare));
  164. xshare &= mask;
  165. }
  166. // For RegXS, + and * should be interpreted bitwise; that is, + is
  167. // really XOR and * is really AND. - is also XOR (the same as +).
  168. // We also include actual XOR operators for convenience
  169. inline RegXS &operator+=(const RegXS &rhs) {
  170. this->xshare ^= rhs.xshare;
  171. return *this;
  172. }
  173. inline RegXS operator+(const RegXS &rhs) const {
  174. RegXS res = *this;
  175. res += rhs;
  176. return res;
  177. }
  178. inline RegXS &operator-=(const RegXS &rhs) {
  179. this->xshare ^= rhs.xshare;
  180. return *this;
  181. }
  182. inline RegXS operator-(const RegXS &rhs) const {
  183. RegXS res = *this;
  184. res -= rhs;
  185. return res;
  186. }
  187. inline RegXS operator-() const {
  188. RegXS res = *this;
  189. return res;
  190. }
  191. inline RegXS &operator*=(value_t rhs) {
  192. this->xshare &= rhs;
  193. return *this;
  194. }
  195. inline RegXS operator*(value_t rhs) const {
  196. RegXS res = *this;
  197. res *= rhs;
  198. return res;
  199. }
  200. // Multiply a scalar by a vector
  201. template <size_t N>
  202. inline std::array<RegXS,N> operator*(std::array<value_t,N> rhs) const {
  203. std::array<RegXS,N> res;
  204. for (size_t i=0;i<N;++i) {
  205. res[i] = *this;
  206. res[i] *= rhs[i];
  207. }
  208. return res;
  209. }
  210. inline RegXS &operator^=(const RegXS &rhs) {
  211. this->xshare ^= rhs.xshare;
  212. return *this;
  213. }
  214. inline RegXS operator^(const RegXS &rhs) const {
  215. RegXS res = *this;
  216. res ^= rhs;
  217. return res;
  218. }
  219. inline RegXS &operator&=(value_t mask) {
  220. this->xshare &= mask;
  221. return *this;
  222. }
  223. inline RegXS operator&(value_t mask) const {
  224. RegXS res = *this;
  225. res &= mask;
  226. return res;
  227. }
  228. // Bit shifting and bit extraction
  229. inline RegXS &operator<<=(nbits_t shift) {
  230. this->xshare <<= shift;
  231. return *this;
  232. }
  233. inline RegXS operator<<(nbits_t shift) const {
  234. RegXS res = *this;
  235. res <<= shift;
  236. return res;
  237. }
  238. inline RegXS &operator>>=(nbits_t shift) {
  239. this->xshare >>= shift;
  240. return *this;
  241. }
  242. inline RegXS operator>>(nbits_t shift) const {
  243. RegXS res = *this;
  244. res >>= shift;
  245. return res;
  246. }
  247. inline RegBS bitat(nbits_t pos) const {
  248. RegBS bs;
  249. bs.set(!!(this->xshare & (value_t(1)<<pos)));
  250. return bs;
  251. }
  252. // Multiply by the local share of the argument, not multiplcation of
  253. // two shared values (two versions)
  254. inline RegXS &mulshareeq(const RegXS &rhs) {
  255. *this *= rhs.xshare;
  256. return *this;
  257. }
  258. inline RegXS mulshare(const RegXS &rhs) const {
  259. RegXS res = *this;
  260. res *= rhs.xshare;
  261. return res;
  262. }
  263. inline void dump() const {
  264. printf("%016lx", xshare);
  265. }
  266. // Extract a bit share of bit bitnum of the XOR-shared register
  267. inline RegBS bit(nbits_t bitnum) const {
  268. RegBS bs;
  269. bs.bshare = !!(xshare & (value_t(1)<<bitnum));
  270. return bs;
  271. }
  272. };
  273. inline value_t combine(const RegXS &A, const RegXS &B,
  274. nbits_t nbits = VALUE_BITS) {
  275. value_t mask = ~0;
  276. if (nbits < VALUE_BITS) {
  277. mask = (value_t(1)<<nbits)-1;
  278. }
  279. return (A.xshare ^ B.xshare) & mask;
  280. }
  281. // Enable templates to specialize on just the basic types RegAS and
  282. // RegXS. Technique from
  283. // https://stackoverflow.com/questions/2430039/one-template-specialization-for-multiple-classes
  284. template <bool B> struct prac_template_bool_type {};
  285. using prac_template_true = prac_template_bool_type<true>;
  286. using prac_template_false = prac_template_bool_type<false>;
  287. template <typename T>
  288. struct prac_basic_Reg_S : prac_template_false
  289. {
  290. static const bool value = false;
  291. };
  292. template<>
  293. struct prac_basic_Reg_S<RegAS>: prac_template_true
  294. {
  295. static const bool value = true;
  296. };
  297. template<>
  298. struct prac_basic_Reg_S<RegXS>: prac_template_true
  299. {
  300. static const bool value = true;
  301. };
  302. // Some useful operations on tuples, vectors, and arrays of the above
  303. // types
  304. template <typename T>
  305. std::tuple<T,T> operator+=(std::tuple<T,T> &A,
  306. const std::tuple<T,T> &B)
  307. {
  308. std::get<0>(A) += std::get<0>(B);
  309. std::get<1>(A) += std::get<1>(B);
  310. return A;
  311. }
  312. template <typename T>
  313. std::tuple<T,T> operator+=(const std::tuple<T&,T&> &A,
  314. const std::tuple<T,T> &B)
  315. {
  316. std::get<0>(A) += std::get<0>(B);
  317. std::get<1>(A) += std::get<1>(B);
  318. return A;
  319. }
  320. template <typename T>
  321. std::tuple<T,T> operator+(const std::tuple<T,T> &A,
  322. const std::tuple<T,T> &B)
  323. {
  324. auto res = A;
  325. res += B;
  326. return res;
  327. }
  328. template <typename T>
  329. std::tuple<T,T> operator-=(const std::tuple<T&,T&> &A,
  330. const std::tuple<T,T> &B)
  331. {
  332. std::get<0>(A) -= std::get<0>(B);
  333. std::get<1>(A) -= std::get<1>(B);
  334. return A;
  335. }
  336. template <typename T>
  337. std::tuple<T,T> operator-=(std::tuple<T,T> &A,
  338. const std::tuple<T,T> &B)
  339. {
  340. std::get<0>(A) -= std::get<0>(B);
  341. std::get<1>(A) -= std::get<1>(B);
  342. return A;
  343. }
  344. template <typename T>
  345. std::tuple<T,T> operator-(const std::tuple<T,T> &A,
  346. const std::tuple<T,T> &B)
  347. {
  348. auto res = A;
  349. res -= B;
  350. return res;
  351. }
  352. template <typename T>
  353. std::tuple<T,T> operator*=(const std::tuple<T&,T&> &A,
  354. const std::tuple<value_t,value_t> &B)
  355. {
  356. std::get<0>(A) *= std::get<0>(B);
  357. std::get<1>(A) *= std::get<1>(B);
  358. return A;
  359. }
  360. template <typename T>
  361. std::tuple<T,T> operator*=(std::tuple<T,T> &A,
  362. const std::tuple<value_t,value_t> &B)
  363. {
  364. std::get<0>(A) *= std::get<0>(B);
  365. std::get<1>(A) *= std::get<1>(B);
  366. return A;
  367. }
  368. template <typename T>
  369. std::tuple<T,T> operator*(const std::tuple<T,T> &A,
  370. const std::tuple<value_t,value_t> &B)
  371. {
  372. auto res = A;
  373. res *= B;
  374. return res;
  375. }
  376. template <typename T, size_t N>
  377. std::tuple<std::array<T,N>,std::array<T,N>> operator*(
  378. const std::tuple<T,T> &A,
  379. const std::tuple<std::array<value_t,N>,std::array<value_t,N>> &B)
  380. {
  381. std::tuple<std::array<T,N>,std::array<T,N>> res;
  382. std::get<0>(res) = std::get<0>(A) * std::get<0>(B);
  383. std::get<1>(res) = std::get<1>(A) * std::get<1>(B);
  384. return res;
  385. }
  386. template <typename S, size_t N>
  387. inline std::array<value_t,N> combine(const std::array<S,N> &A,
  388. const std::array<S,N> &B,
  389. nbits_t nbits = VALUE_BITS) {
  390. std::array<value_t,N> res;
  391. for (size_t i=0;i<N;++i) {
  392. res[i] = combine(A[i], B[i], nbits);
  393. }
  394. return res;
  395. }
  396. template <typename S, size_t N>
  397. inline std::tuple<std::array<value_t,N>,std::array<value_t,N>>
  398. combine(const std::tuple<std::array<S,N>,std::array<S,N>> &A,
  399. const std::tuple<std::array<S,N>,std::array<S,N>> &B,
  400. nbits_t nbits = VALUE_BITS) {
  401. return std::make_tuple(
  402. combine(std::get<0>(A), std::get<0>(B), nbits),
  403. combine(std::get<1>(A), std::get<1>(B), nbits));
  404. }
  405. template <typename T>
  406. std::tuple<T,T,T> operator+=(const std::tuple<T&,T&,T&> &A,
  407. const std::tuple<T,T,T> &B)
  408. {
  409. std::get<0>(A) += std::get<0>(B);
  410. std::get<1>(A) += std::get<1>(B);
  411. std::get<2>(A) += std::get<2>(B);
  412. return A;
  413. }
  414. template <typename T>
  415. std::tuple<T,T,T> operator+=(std::tuple<T,T,T> &A,
  416. const std::tuple<T,T,T> &B)
  417. {
  418. std::get<0>(A) += std::get<0>(B);
  419. std::get<1>(A) += std::get<1>(B);
  420. std::get<2>(A) += std::get<2>(B);
  421. return A;
  422. }
  423. template <typename T>
  424. std::tuple<T,T,T> operator+(const std::tuple<T,T,T> &A,
  425. const std::tuple<T,T,T> &B)
  426. {
  427. auto res = A;
  428. res += B;
  429. return res;
  430. }
  431. template <typename T>
  432. std::tuple<T,T,T> operator-=(const std::tuple<T&,T&,T&> &A,
  433. const std::tuple<T,T,T> &B)
  434. {
  435. std::get<0>(A) -= std::get<0>(B);
  436. std::get<1>(A) -= std::get<1>(B);
  437. std::get<2>(A) -= std::get<2>(B);
  438. return A;
  439. }
  440. template <typename T>
  441. std::tuple<T,T,T> operator-=(std::tuple<T,T,T> &A,
  442. const std::tuple<T,T,T> &B)
  443. {
  444. std::get<0>(A) -= std::get<0>(B);
  445. std::get<1>(A) -= std::get<1>(B);
  446. std::get<2>(A) -= std::get<2>(B);
  447. return A;
  448. }
  449. template <typename T>
  450. std::tuple<T,T,T> operator-(const std::tuple<T,T,T> &A,
  451. const std::tuple<T,T,T> &B)
  452. {
  453. auto res = A;
  454. res -= B;
  455. return res;
  456. }
  457. template <typename T>
  458. std::tuple<T,T,T> operator*=(const std::tuple<T&,T&,T&> &A,
  459. const std::tuple<value_t,value_t,value_t> &B)
  460. {
  461. std::get<0>(A) *= std::get<0>(B);
  462. std::get<1>(A) *= std::get<1>(B);
  463. std::get<2>(A) *= std::get<2>(B);
  464. return A;
  465. }
  466. template <typename T>
  467. std::tuple<T,T,T> operator*=(std::tuple<T,T,T> &A,
  468. const std::tuple<value_t,value_t,value_t> &B)
  469. {
  470. std::get<0>(A) *= std::get<0>(B);
  471. std::get<1>(A) *= std::get<1>(B);
  472. std::get<2>(A) *= std::get<2>(B);
  473. return A;
  474. }
  475. template <typename T>
  476. std::tuple<T,T,T> operator*(const std::tuple<T,T,T> &A,
  477. const std::tuple<value_t,value_t,value_t> &B)
  478. {
  479. auto res = A;
  480. res *= B;
  481. return res;
  482. }
  483. template <typename T, size_t N>
  484. std::tuple<std::array<T,N>,std::array<T,N>,std::array<T,N>> operator*(
  485. const std::tuple<T,T,T> &A,
  486. const std::tuple<std::array<value_t,N>,std::array<value_t,N>,std::array<value_t,N>> &B)
  487. {
  488. std::tuple<std::array<T,N>,std::array<T,N>,std::array<T,N>> res;
  489. std::get<0>(res) = std::get<0>(A) * std::get<0>(B);
  490. std::get<1>(res) = std::get<1>(A) * std::get<1>(B);
  491. std::get<2>(res) = std::get<2>(A) * std::get<2>(B);
  492. return res;
  493. }
  494. inline std::vector<RegAS> operator-(const std::vector<RegAS> &A)
  495. {
  496. std::vector<RegAS> res;
  497. for (const auto &v : A) {
  498. res.push_back(-v);
  499. }
  500. return res;
  501. }
  502. inline std::vector<RegXS> operator-(const std::vector<RegXS> &A)
  503. {
  504. return A;
  505. }
  506. inline std::vector<RegBS> operator-(const std::vector<RegBS> &A)
  507. {
  508. return A;
  509. }
  510. template <size_t N>
  511. inline std::vector<RegAS> operator-(const std::array<RegAS,N> &A)
  512. {
  513. std::vector<RegAS> res;
  514. for (const auto &v : A) {
  515. res.push_back(-v);
  516. }
  517. return res;
  518. }
  519. template <size_t N>
  520. inline std::array<RegXS,N> operator-(const std::array<RegXS,N> &A)
  521. {
  522. return A;
  523. }
  524. template <size_t N>
  525. inline std::array<RegBS,N> operator-(const std::array<RegBS,N> &A)
  526. {
  527. return A;
  528. }
  529. template <typename S, size_t N>
  530. inline std::array<S,N> &operator+=(std::array<S,N> &A, const std::array<S,N> &B)
  531. {
  532. for (size_t i=0;i<N;++i) {
  533. A[i] += B[i];
  534. }
  535. return A;
  536. }
  537. template <typename S, size_t N>
  538. inline std::array<S,N> &operator-=(std::array<S,N> &A, const std::array<S,N> &B)
  539. {
  540. for (size_t i=0;i<N;++i) {
  541. A[i] -= B[i];
  542. }
  543. return A;
  544. }
  545. template <typename S, size_t N>
  546. inline std::array<S,N> &operator^=(std::array<S,N> &A, const std::array<S,N> &B)
  547. {
  548. for (size_t i=0;i<N;++i) {
  549. A[i] ^= B[i];
  550. }
  551. return A;
  552. }
  553. template <typename S, size_t N>
  554. inline std::tuple<std::array<value_t,N>,std::array<value_t,N>,std::array<value_t,N>>
  555. combine(
  556. const std::tuple<std::array<S,N>,std::array<S,N>,std::array<S,N>> &A,
  557. const std::tuple<std::array<S,N>,std::array<S,N>,std::array<S,N>> &B,
  558. nbits_t nbits = VALUE_BITS) {
  559. return std::make_tuple(
  560. combine(std::get<0>(A), std::get<0>(B), nbits),
  561. combine(std::get<1>(A), std::get<1>(B), nbits),
  562. combine(std::get<2>(A), std::get<2>(B), nbits));
  563. }
  564. // The _maximum_ number of bits in an MPC address; the actual size of
  565. // the memory will typically be set at runtime, but it cannot exceed
  566. // this value. It is more efficient (in terms of communication) in some
  567. // places for this value to be at most 32.
  568. #ifndef ADDRESS_MAX_BITS
  569. #define ADDRESS_MAX_BITS 32
  570. #endif
  571. // Addresses of MPC secret-shared memory are of this type
  572. #if ADDRESS_MAX_BITS <= 32
  573. using address_t = uint32_t;
  574. #elif ADDRESS_MAX_BITS <= 64
  575. using address_t = uint64_t;
  576. #else
  577. #error "Unsupported value of ADDRESS_MAX_BITS"
  578. #endif
  579. #if ADDRESS_MAX_BITS > VALUE_BITS
  580. #error "VALUE_BITS must be at least as large as ADDRESS_MAX_BITS"
  581. #endif
  582. // A multiplication triple is a triple (X0,Y0,Z0) held by P0 (and
  583. // correspondingly (X1,Y1,Z1) held by P1), with all values random,
  584. // but subject to the relation that X0*Y1 + Y0*X1 = Z0+Z1
  585. using MultTriple = std::tuple<value_t, value_t, value_t>;
  586. // The *Name structs are a way to get strings representing the names of
  587. // the types as would be given to preprocessing to create them in
  588. // advance.
  589. struct MultTripleName { static constexpr const char *name = "m"; };
  590. // A half-triple is (X0,Z0) held by P0 (and correspondingly (Y1,Z1) held
  591. // by P1), with all values random, but subject to the relation that
  592. // X0*Y1 = Z0+Z1
  593. using HalfTriple = std::tuple<value_t, value_t>;
  594. struct HalfTripleName { static constexpr const char *name = "h"; };
  595. // An AND triple is a triple (X0,Y0,Z0) held by P0 (and correspondingly
  596. // (X1,Y1,Z1) held by P1), with all values random, but subject to the
  597. // relation that X0&Y1 ^ Y0&X1 = Z0^Z1
  598. using AndTriple = std::tuple<value_t, value_t, value_t>;
  599. struct AndTripleName { static constexpr const char *name = "a"; };
  600. // The type of nodes in a DPF. This must be at least as many bits as
  601. // the security parameter, and at least twice as many bits as value_t.
  602. using DPFnode = __m128i;
  603. // A Select triple for type V (V is DPFnode, value_t, or bit_t) is a
  604. // triple of (X0,Y0,Z0) where X0 is a bit and Y0 and Z0 are Vs held by
  605. // P0 (and correspondingly (X1,Y1,Z1) held by P1), with all values
  606. // random, but subject to the relation that (X0*Y1) ^ (Y0*X1) = Z0^Z1.
  607. // This is a struct instead of a tuple for alignment reasons.
  608. template <typename V>
  609. struct SelectTriple {
  610. bit_t X;
  611. V Y, Z;
  612. };
  613. // Of the three options for V, we only ever store V = value_t
  614. struct ValSelectTripleName { static constexpr const char *name = "s"; };
  615. // These are defined in rdpf.hpp, but declared here to avoid cyclic
  616. // header dependencies.
  617. template <nbits_t WIDTH> struct RDPFPair;
  618. struct RDPFPairName { static constexpr const char *name = "r"; };
  619. template <nbits_t WIDTH> struct RDPFTriple;
  620. struct RDPFTripleName { static constexpr const char *name = "r"; };
  621. struct CDPF;
  622. struct CDPFName { static constexpr const char *name = "c"; };
  623. // We want the I/O (using << and >>) for many classes
  624. // to just be a common thing: write out the bytes
  625. // straight from memory
  626. #define DEFAULT_IO(CLASSNAME) \
  627. template <typename T> \
  628. T& operator>>(T& is, CLASSNAME &x) \
  629. { \
  630. is.read((char *)&x, sizeof(x)); \
  631. return is; \
  632. } \
  633. \
  634. template <typename T> \
  635. T& operator<<(T& os, const CLASSNAME &x) \
  636. { \
  637. os.write((const char *)&x, sizeof(x)); \
  638. return os; \
  639. }
  640. // Default I/O for various types
  641. DEFAULT_IO(DPFnode)
  642. DEFAULT_IO(RegBS)
  643. DEFAULT_IO(RegAS)
  644. DEFAULT_IO(RegXS)
  645. DEFAULT_IO(MultTriple)
  646. DEFAULT_IO(HalfTriple)
  647. // We don't need one for AndTriple because it's exactly the same type as
  648. // MultTriple
  649. // I/O for arrays
  650. template <typename T, typename S, size_t N>
  651. T& operator>>(T& is, std::array<S,N> &x)
  652. {
  653. for (size_t i=0;i<N;++i) {
  654. is >> x[i];
  655. }
  656. return is;
  657. }
  658. template <typename T, typename S, size_t N>
  659. T& operator<<(T& os, const std::array<S,N> &x)
  660. {
  661. for (size_t i=0;i<N;++i) {
  662. os << x[i];
  663. }
  664. return os;
  665. }
  666. // I/O for SelectTriples
  667. template <typename T, typename V>
  668. T& operator>>(T& is, SelectTriple<V> &x)
  669. {
  670. is.read((char *)&x.X, sizeof(x.X));
  671. is.read((char *)&x.Y, sizeof(x.Y));
  672. is.read((char *)&x.Z, sizeof(x.Z));
  673. return is;
  674. }
  675. template <typename T, typename V>
  676. T& operator<<(T& os, const SelectTriple<V> &x)
  677. {
  678. os.write((const char *)&x.X, sizeof(x.X));
  679. os.write((const char *)&x.Y, sizeof(x.Y));
  680. os.write((const char *)&x.Z, sizeof(x.Z));
  681. return os;
  682. }
  683. // And for pairs and triples
  684. #define DEFAULT_TUPLE_IO(CLASSNAME) \
  685. template <typename T> \
  686. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME> &x) \
  687. { \
  688. is >> std::get<0>(x) >> std::get<1>(x); \
  689. return is; \
  690. } \
  691. \
  692. template <typename T> \
  693. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME> &x) \
  694. { \
  695. os << std::get<0>(x) << std::get<1>(x); \
  696. return os; \
  697. } \
  698. \
  699. template <typename T> \
  700. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  701. { \
  702. is >> std::get<0>(x) >> std::get<1>(x) >> std::get<2>(x); \
  703. return is; \
  704. } \
  705. \
  706. template <typename T> \
  707. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  708. { \
  709. os << std::get<0>(x) << std::get<1>(x) << std::get<2>(x); \
  710. return os; \
  711. }
  712. DEFAULT_TUPLE_IO(RegAS)
  713. DEFAULT_TUPLE_IO(RegXS)
  714. // And for pairs and triples of arrays
  715. template <typename T, typename S, size_t N>
  716. T& operator>>(T& is, std::tuple<std::array<S,N>, std::array<S,N>> &x)
  717. {
  718. is >> std::get<0>(x) >> std::get<1>(x);
  719. return is;
  720. }
  721. template <typename T, typename S, size_t N>
  722. T& operator<<(T& os, const std::tuple<std::array<S,N>, std::array<S,N>> &x)
  723. {
  724. os << std::get<0>(x) << std::get<1>(x);
  725. return os;
  726. }
  727. template <typename T, typename S, size_t N>
  728. T& operator>>(T& is, std::tuple<std::array<S,N>, std::array<S,N>, std::array<S,N>> &x)
  729. {
  730. is >> std::get<0>(x) >> std::get<1>(x) >> std::get<2>(x);
  731. return is;
  732. }
  733. template <typename T, typename S, size_t N>
  734. T& operator<<(T& os, const std::tuple<std::array<S,N>, std::array<S,N>, std::array<S,N>> &x)
  735. {
  736. os << std::get<0>(x) << std::get<1>(x) << std::get<2>(x);
  737. return os;
  738. }
  739. enum ProcessingMode {
  740. MODE_ONLINE, // Online mode, after preprocessing has been done
  741. MODE_PREPROCESSING, // Preprocessing mode
  742. MODE_ONLINEONLY // Online-only mode, where all computations are
  743. }; // done online
  744. #endif