types.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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. // The basic types just have one value
  40. static const size_t WIDTH = 1;
  41. RegAS() : ashare(0) {}
  42. inline value_t share() const { return ashare; }
  43. inline void set(value_t s) { ashare = s; }
  44. // Set each side's share to a random value nbits bits long
  45. inline void randomize(size_t nbits = VALUE_BITS) {
  46. value_t mask = MASKBITS(nbits);
  47. arc4random_buf(&ashare, sizeof(ashare));
  48. ashare &= mask;
  49. }
  50. inline RegAS &operator+=(const RegAS &rhs) {
  51. this->ashare += rhs.ashare;
  52. return *this;
  53. }
  54. inline RegAS operator+(const RegAS &rhs) const {
  55. RegAS res = *this;
  56. res += rhs;
  57. return res;
  58. }
  59. inline RegAS &operator-=(const RegAS &rhs) {
  60. this->ashare -= rhs.ashare;
  61. return *this;
  62. }
  63. inline RegAS operator-(const RegAS &rhs) const {
  64. RegAS res = *this;
  65. res -= rhs;
  66. return res;
  67. }
  68. inline RegAS operator-() const {
  69. RegAS res = *this;
  70. res.ashare = -res.ashare;
  71. return res;
  72. }
  73. inline RegAS &operator*=(value_t rhs) {
  74. this->ashare *= rhs;
  75. return *this;
  76. }
  77. inline RegAS operator*(value_t rhs) const {
  78. RegAS res = *this;
  79. res *= rhs;
  80. return res;
  81. }
  82. inline RegAS &operator&=(value_t mask) {
  83. this->ashare &= mask;
  84. return *this;
  85. }
  86. inline RegAS operator&(value_t mask) const {
  87. RegAS res = *this;
  88. res &= mask;
  89. return res;
  90. }
  91. // Multiply by the local share of the argument, not multiplcation of
  92. // two shared values (two versions)
  93. inline RegAS &mulshareeq(const RegAS &rhs) {
  94. *this *= rhs.ashare;
  95. return *this;
  96. }
  97. inline RegAS mulshare(const RegAS &rhs) const {
  98. RegAS res = *this;
  99. res *= rhs.ashare;
  100. return res;
  101. }
  102. inline void dump() const {
  103. printf("%016lx", ashare);
  104. }
  105. };
  106. inline value_t combine(const RegAS &A, const RegAS &B,
  107. nbits_t nbits = VALUE_BITS) {
  108. value_t mask = ~0;
  109. if (nbits < VALUE_BITS) {
  110. mask = (value_t(1)<<nbits)-1;
  111. }
  112. return (A.ashare + B.ashare) & mask;
  113. }
  114. // The type of a register holding a bit share
  115. struct RegBS {
  116. bit_t bshare;
  117. RegBS() : bshare(0) {}
  118. inline bit_t share() const { return bshare; }
  119. inline void set(bit_t s) { bshare = s; }
  120. // Set each side's share to a random bit
  121. inline void randomize() {
  122. unsigned char randb;
  123. arc4random_buf(&randb, sizeof(randb));
  124. bshare = randb & 1;
  125. }
  126. inline RegBS &operator^=(const RegBS &rhs) {
  127. this->bshare ^= rhs.bshare;
  128. return *this;
  129. }
  130. inline RegBS operator^(const RegBS &rhs) const {
  131. RegBS res = *this;
  132. res ^= rhs;
  133. return res;
  134. }
  135. inline RegBS &operator^=(const bit_t &rhs) {
  136. this->bshare ^= rhs;
  137. return *this;
  138. }
  139. inline RegBS operator^(const bit_t &rhs) const {
  140. RegBS res = *this;
  141. res ^= rhs;
  142. return res;
  143. }
  144. };
  145. // The type of a register holding an XOR share of a value
  146. struct RegXS {
  147. value_t xshare;
  148. // The basic types just have one value
  149. static const size_t WIDTH = 1;
  150. RegXS() : xshare(0) {}
  151. RegXS(const RegBS &b) { xshare = b.bshare ? ~0 : 0; }
  152. inline value_t share() const { return xshare; }
  153. inline void set(value_t s) { xshare = s; }
  154. // Set each side's share to a random value nbits bits long
  155. inline void randomize(size_t nbits = VALUE_BITS) {
  156. value_t mask = MASKBITS(nbits);
  157. arc4random_buf(&xshare, sizeof(xshare));
  158. xshare &= mask;
  159. }
  160. // For RegXS, + and * should be interpreted bitwise; that is, + is
  161. // really XOR and * is really AND. - is also XOR (the same as +).
  162. // We also include actual XOR operators for convenience
  163. inline RegXS &operator+=(const RegXS &rhs) {
  164. this->xshare ^= rhs.xshare;
  165. return *this;
  166. }
  167. inline RegXS operator+(const RegXS &rhs) const {
  168. RegXS res = *this;
  169. res += rhs;
  170. return res;
  171. }
  172. inline RegXS &operator-=(const RegXS &rhs) {
  173. this->xshare ^= rhs.xshare;
  174. return *this;
  175. }
  176. inline RegXS operator-(const RegXS &rhs) const {
  177. RegXS res = *this;
  178. res -= rhs;
  179. return res;
  180. }
  181. inline RegXS operator-() const {
  182. RegXS res = *this;
  183. return res;
  184. }
  185. inline RegXS &operator*=(value_t rhs) {
  186. this->xshare &= rhs;
  187. return *this;
  188. }
  189. inline RegXS operator*(value_t rhs) const {
  190. RegXS res = *this;
  191. res *= rhs;
  192. return res;
  193. }
  194. inline RegXS &operator^=(const RegXS &rhs) {
  195. this->xshare ^= rhs.xshare;
  196. return *this;
  197. }
  198. inline RegXS operator^(const RegXS &rhs) const {
  199. RegXS res = *this;
  200. res ^= rhs;
  201. return res;
  202. }
  203. inline RegXS &operator&=(value_t mask) {
  204. this->xshare &= mask;
  205. return *this;
  206. }
  207. inline RegXS operator&(value_t mask) const {
  208. RegXS res = *this;
  209. res &= mask;
  210. return res;
  211. }
  212. // Multiply by the local share of the argument, not multiplcation of
  213. // two shared values (two versions)
  214. inline RegXS &mulshareeq(const RegXS &rhs) {
  215. *this *= rhs.xshare;
  216. return *this;
  217. }
  218. inline RegXS mulshare(const RegXS &rhs) const {
  219. RegXS res = *this;
  220. res *= rhs.xshare;
  221. return res;
  222. }
  223. inline void dump() const {
  224. printf("%016lx", xshare);
  225. }
  226. // Extract a bit share of bit bitnum of the XOR-shared register
  227. inline RegBS bit(nbits_t bitnum) const {
  228. RegBS bs;
  229. bs.bshare = !!(xshare & (value_t(1)<<bitnum));
  230. return bs;
  231. }
  232. };
  233. inline value_t combine(const RegXS &A, const RegXS &B,
  234. nbits_t nbits = VALUE_BITS) {
  235. value_t mask = ~0;
  236. if (nbits < VALUE_BITS) {
  237. mask = (value_t(1)<<nbits)-1;
  238. }
  239. return (A.xshare ^ B.xshare) & mask;
  240. }
  241. // Enable templates to specialize on just the basic types RegAS and
  242. // RegXS. Technique from
  243. // https://stackoverflow.com/questions/2430039/one-template-specialization-for-multiple-classes
  244. template <bool B> struct prac_template_bool_type {};
  245. using prac_template_true = prac_template_bool_type<true>;
  246. using prac_template_false = prac_template_bool_type<false>;
  247. template <typename T>
  248. struct prac_basic_Reg_S : prac_template_false
  249. {
  250. static const bool value = false;
  251. };
  252. template<>
  253. struct prac_basic_Reg_S<RegAS>: prac_template_true
  254. {
  255. static const bool value = true;
  256. };
  257. template<>
  258. struct prac_basic_Reg_S<RegXS>: prac_template_true
  259. {
  260. static const bool value = true;
  261. };
  262. // Some useful operations on tuples, vectors, and arrays of the above
  263. // types
  264. template <typename T>
  265. std::tuple<T,T> operator+=(std::tuple<T,T> &A,
  266. const std::tuple<T,T> &B)
  267. {
  268. std::get<0>(A) += std::get<0>(B);
  269. std::get<1>(A) += std::get<1>(B);
  270. return A;
  271. }
  272. template <typename T>
  273. std::tuple<T,T> operator+=(const std::tuple<T&,T&> &A,
  274. const std::tuple<T,T> &B)
  275. {
  276. std::get<0>(A) += std::get<0>(B);
  277. std::get<1>(A) += std::get<1>(B);
  278. return A;
  279. }
  280. template <typename T>
  281. std::tuple<T,T> operator+(const std::tuple<T,T> &A,
  282. const std::tuple<T,T> &B)
  283. {
  284. auto res = A;
  285. res += B;
  286. return res;
  287. }
  288. template <typename T>
  289. std::tuple<T,T> operator-=(const std::tuple<T&,T&> &A,
  290. const std::tuple<T,T> &B)
  291. {
  292. std::get<0>(A) -= std::get<0>(B);
  293. std::get<1>(A) -= std::get<1>(B);
  294. return A;
  295. }
  296. template <typename T>
  297. std::tuple<T,T> operator-=(std::tuple<T,T> &A,
  298. const std::tuple<T,T> &B)
  299. {
  300. std::get<0>(A) -= std::get<0>(B);
  301. std::get<1>(A) -= std::get<1>(B);
  302. return A;
  303. }
  304. template <typename T>
  305. std::tuple<T,T> operator-(const std::tuple<T,T> &A,
  306. const std::tuple<T,T> &B)
  307. {
  308. auto res = A;
  309. res -= B;
  310. return res;
  311. }
  312. template <typename T>
  313. std::tuple<T,T> operator*=(const std::tuple<T&,T&> &A,
  314. const std::tuple<value_t,value_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*=(std::tuple<T,T> &A,
  322. const std::tuple<value_t,value_t> &B)
  323. {
  324. std::get<0>(A) *= std::get<0>(B);
  325. std::get<1>(A) *= std::get<1>(B);
  326. return A;
  327. }
  328. template <typename T>
  329. std::tuple<T,T> operator*(const std::tuple<T,T> &A,
  330. const std::tuple<value_t,value_t> &B)
  331. {
  332. auto res = A;
  333. res *= B;
  334. return res;
  335. }
  336. template <typename T>
  337. inline std::tuple<value_t,value_t> combine(
  338. const std::tuple<T,T> &A, const std::tuple<T,T> &B,
  339. nbits_t nbits = VALUE_BITS) {
  340. return std::make_tuple(
  341. combine(std::get<0>(A), std::get<0>(B), nbits),
  342. combine(std::get<1>(A), std::get<1>(B), nbits));
  343. }
  344. template <typename T>
  345. std::tuple<T,T,T> operator+=(const std::tuple<T&,T&,T&> &A,
  346. const std::tuple<T,T,T> &B)
  347. {
  348. std::get<0>(A) += std::get<0>(B);
  349. std::get<1>(A) += std::get<1>(B);
  350. std::get<2>(A) += std::get<2>(B);
  351. return A;
  352. }
  353. template <typename T>
  354. std::tuple<T,T,T> operator+=(std::tuple<T,T,T> &A,
  355. const std::tuple<T,T,T> &B)
  356. {
  357. std::get<0>(A) += std::get<0>(B);
  358. std::get<1>(A) += std::get<1>(B);
  359. std::get<2>(A) += std::get<2>(B);
  360. return A;
  361. }
  362. template <typename T>
  363. std::tuple<T,T,T> operator+(const std::tuple<T,T,T> &A,
  364. const std::tuple<T,T,T> &B)
  365. {
  366. auto res = A;
  367. res += B;
  368. return res;
  369. }
  370. template <typename T>
  371. std::tuple<T,T,T> operator-=(const std::tuple<T&,T&,T&> &A,
  372. const std::tuple<T,T,T> &B)
  373. {
  374. std::get<0>(A) -= std::get<0>(B);
  375. std::get<1>(A) -= std::get<1>(B);
  376. std::get<2>(A) -= std::get<2>(B);
  377. return A;
  378. }
  379. template <typename T>
  380. std::tuple<T,T,T> operator-=(std::tuple<T,T,T> &A,
  381. const std::tuple<T,T,T> &B)
  382. {
  383. std::get<0>(A) -= std::get<0>(B);
  384. std::get<1>(A) -= std::get<1>(B);
  385. std::get<2>(A) -= std::get<2>(B);
  386. return A;
  387. }
  388. template <typename T>
  389. std::tuple<T,T,T> operator-(const std::tuple<T,T,T> &A,
  390. const std::tuple<T,T,T> &B)
  391. {
  392. auto res = A;
  393. res -= B;
  394. return res;
  395. }
  396. template <typename T>
  397. std::tuple<T,T,T> operator*=(const std::tuple<T&,T&,T&> &A,
  398. const std::tuple<value_t,value_t,value_t> &B)
  399. {
  400. std::get<0>(A) *= std::get<0>(B);
  401. std::get<1>(A) *= std::get<1>(B);
  402. std::get<2>(A) *= std::get<2>(B);
  403. return A;
  404. }
  405. template <typename T>
  406. std::tuple<T,T,T> operator*=(std::tuple<T,T,T> &A,
  407. const std::tuple<value_t,value_t,value_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*(const std::tuple<T,T,T> &A,
  416. const std::tuple<value_t,value_t,value_t> &B)
  417. {
  418. auto res = A;
  419. res *= B;
  420. return res;
  421. }
  422. inline std::vector<RegAS> operator-(const std::vector<RegAS> &A)
  423. {
  424. std::vector<RegAS> res;
  425. for (const auto &v : A) {
  426. res.push_back(-v);
  427. }
  428. return res;
  429. }
  430. inline std::vector<RegXS> operator-(const std::vector<RegXS> &A)
  431. {
  432. return A;
  433. }
  434. inline std::vector<RegBS> operator-(const std::vector<RegBS> &A)
  435. {
  436. return A;
  437. }
  438. template <size_t N>
  439. inline std::vector<RegAS> operator-(const std::array<RegAS,N> &A)
  440. {
  441. std::vector<RegAS> res;
  442. for (const auto &v : A) {
  443. res.push_back(-v);
  444. }
  445. return res;
  446. }
  447. template <size_t N>
  448. inline std::array<RegXS,N> operator-(const std::array<RegXS,N> &A)
  449. {
  450. return A;
  451. }
  452. template <size_t N>
  453. inline std::array<RegBS,N> operator-(const std::array<RegBS,N> &A)
  454. {
  455. return A;
  456. }
  457. template <typename T>
  458. inline std::tuple<value_t,value_t,value_t> combine(
  459. const std::tuple<T,T,T> &A, const std::tuple<T,T,T> &B,
  460. nbits_t nbits = VALUE_BITS) {
  461. return std::make_tuple(
  462. combine(std::get<0>(A), std::get<0>(B), nbits),
  463. combine(std::get<1>(A), std::get<1>(B), nbits),
  464. combine(std::get<2>(A), std::get<2>(B), nbits));
  465. }
  466. // The _maximum_ number of bits in an MPC address; the actual size of
  467. // the memory will typically be set at runtime, but it cannot exceed
  468. // this value. It is more efficient (in terms of communication) in some
  469. // places for this value to be at most 32.
  470. #ifndef ADDRESS_MAX_BITS
  471. #define ADDRESS_MAX_BITS 32
  472. #endif
  473. // Addresses of MPC secret-shared memory are of this type
  474. #if ADDRESS_MAX_BITS <= 32
  475. using address_t = uint32_t;
  476. #elif ADDRESS_MAX_BITS <= 64
  477. using address_t = uint64_t;
  478. #else
  479. #error "Unsupported value of ADDRESS_MAX_BITS"
  480. #endif
  481. #if ADDRESS_MAX_BITS > VALUE_BITS
  482. #error "VALUE_BITS must be at least as large as ADDRESS_MAX_BITS"
  483. #endif
  484. // A multiplication triple is a triple (X0,Y0,Z0) held by P0 (and
  485. // correspondingly (X1,Y1,Z1) held by P1), with all values random,
  486. // but subject to the relation that X0*Y1 + Y0*X1 = Z0+Z1
  487. using MultTriple = std::tuple<value_t, value_t, value_t>;
  488. // The *Name structs are a way to get strings representing the names of
  489. // the types as would be given to preprocessing to create them in
  490. // advance.
  491. struct MultTripleName { static constexpr const char *name = "t"; };
  492. // A half-triple is (X0,Z0) held by P0 (and correspondingly (Y1,Z1) held
  493. // by P1), with all values random, but subject to the relation that
  494. // X0*Y1 = Z0+Z1
  495. using HalfTriple = std::tuple<value_t, value_t>;
  496. struct HalfTripleName { static constexpr const char *name = "h"; };
  497. // The type of nodes in a DPF. This must be at least as many bits as
  498. // the security parameter, and at least twice as many bits as value_t.
  499. using DPFnode = __m128i;
  500. // A Select triple is a triple of (X0,Y0,Z0) where X0 is a bit and Y0
  501. // and Z0 are DPFnodes held by P0 (and correspondingly (X1,Y1,Z1) held
  502. // by P1), with all values random, but subject to the relation that
  503. // (X0*Y1) ^ (Y0*X1) = Z0^Z1. These are only used while creating RDPFs
  504. // in the preprocessing phase, so we never need to store them. This is
  505. // a struct instead of a tuple for alignment reasons.
  506. struct SelectTriple {
  507. bit_t X;
  508. DPFnode Y, Z;
  509. };
  510. // These are defined in rdpf.hpp, but declared here to avoid cyclic
  511. // header dependencies.
  512. struct RDPFPair;
  513. struct RDPFPairName { static constexpr const char *name = "r"; };
  514. struct RDPFTriple;
  515. struct RDPFTripleName { static constexpr const char *name = "r"; };
  516. struct CDPF;
  517. struct CDPFName { static constexpr const char *name = "c"; };
  518. // We want the I/O (using << and >>) for many classes
  519. // to just be a common thing: write out the bytes
  520. // straight from memory
  521. #define DEFAULT_IO(CLASSNAME) \
  522. template <typename T> \
  523. T& operator>>(T& is, CLASSNAME &x) \
  524. { \
  525. is.read((char *)&x, sizeof(x)); \
  526. return is; \
  527. } \
  528. \
  529. template <typename T> \
  530. T& operator<<(T& os, const CLASSNAME &x) \
  531. { \
  532. os.write((const char *)&x, sizeof(x)); \
  533. return os; \
  534. }
  535. // Default I/O for various types
  536. DEFAULT_IO(DPFnode)
  537. DEFAULT_IO(RegBS)
  538. DEFAULT_IO(RegAS)
  539. DEFAULT_IO(RegXS)
  540. DEFAULT_IO(MultTriple)
  541. DEFAULT_IO(HalfTriple)
  542. // And for pairs and triples
  543. #define DEFAULT_TUPLE_IO(CLASSNAME) \
  544. template <typename T> \
  545. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME> &x) \
  546. { \
  547. is >> std::get<0>(x) >> std::get<1>(x); \
  548. return is; \
  549. } \
  550. \
  551. template <typename T> \
  552. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME> &x) \
  553. { \
  554. os << std::get<0>(x) << std::get<1>(x); \
  555. return os; \
  556. } \
  557. \
  558. template <typename T> \
  559. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  560. { \
  561. is >> std::get<0>(x) >> std::get<1>(x) >> std::get<2>(x); \
  562. return is; \
  563. } \
  564. \
  565. template <typename T> \
  566. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  567. { \
  568. os << std::get<0>(x) << std::get<1>(x) << std::get<2>(x); \
  569. return os; \
  570. }
  571. DEFAULT_TUPLE_IO(RegAS)
  572. DEFAULT_TUPLE_IO(RegXS)
  573. enum ProcessingMode {
  574. MODE_ONLINE, // Online mode, after preprocessing has been done
  575. MODE_PREPROCESSING, // Preprocessing mode
  576. MODE_ONLINEONLY // Online-only mode, where all computations are
  577. }; // done online
  578. #endif