types.hpp 24 KB

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