types.hpp 24 KB

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