types.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. #ifndef __OBLIVDS_TYPES_HPP__
  2. #define __OBLIVDS_TYPES_HPP__
  3. #include <tuple>
  4. #include <cstdint>
  5. #include <x86intrin.h> // SSE and AVX intrinsics
  6. #include <bsd/stdlib.h> // arc4random_buf
  7. // The number of bits in an MPC secret-shared memory word
  8. #ifndef VALUE_BITS
  9. #define VALUE_BITS 64
  10. #endif
  11. // Values in MPC secret-shared memory are of this type.
  12. // This is the type of the underlying shared value, not the types of the
  13. // shares themselves.
  14. #if VALUE_BITS == 64
  15. using value_t = uint64_t;
  16. #elif VALUE_BITS == 32
  17. using value_t = uint32_t;
  18. #else
  19. #error "Unsupported value of VALUE_BITS"
  20. #endif
  21. // Secret-shared bits are of this type. Note that it is standards
  22. // compliant to treat a bool as an unsigned integer type with values 0
  23. // and 1.
  24. using bit_t = bool;
  25. // Counts of the number of bits in a value are of this type, which must
  26. // be large enough to store the _value_ VALUE_BITS
  27. using nbits_t = uint8_t;
  28. // Convert a number of bits to the number of bytes required to store (or
  29. // more to the point, send) them.
  30. #define BITBYTES(nbits) (((nbits)+7)>>3)
  31. // A mask of this many bits; the test is to prevent 1<<nbits from
  32. // overflowing if nbits == VALUE_BITS
  33. #define MASKBITS(nbits) (((nbits) < VALUE_BITS) ? (value_t(1)<<(nbits))-1 : ~0)
  34. // The type of a register holding an additive share of a value
  35. struct RegAS {
  36. value_t ashare;
  37. RegAS() : ashare(0) {}
  38. inline value_t share() const { return ashare; }
  39. inline void set(value_t s) { ashare = s; }
  40. // Set each side's share to a random value nbits bits long
  41. inline void randomize(size_t nbits = VALUE_BITS) {
  42. value_t mask = MASKBITS(nbits);
  43. arc4random_buf(&ashare, sizeof(ashare));
  44. ashare &= mask;
  45. }
  46. inline RegAS &operator+=(const RegAS &rhs) {
  47. this->ashare += rhs.ashare;
  48. return *this;
  49. }
  50. inline RegAS operator+(const RegAS &rhs) const {
  51. RegAS res = *this;
  52. res += rhs;
  53. return res;
  54. }
  55. inline RegAS &operator-=(const RegAS &rhs) {
  56. this->ashare -= rhs.ashare;
  57. return *this;
  58. }
  59. inline RegAS operator-(const RegAS &rhs) const {
  60. RegAS res = *this;
  61. res -= rhs;
  62. return res;
  63. }
  64. inline RegAS operator-() const {
  65. RegAS res = *this;
  66. res.ashare = -res.ashare;
  67. return res;
  68. }
  69. inline RegAS &operator*=(value_t rhs) {
  70. this->ashare *= rhs;
  71. return *this;
  72. }
  73. inline RegAS operator*(value_t rhs) const {
  74. RegAS res = *this;
  75. res *= rhs;
  76. return res;
  77. }
  78. inline RegAS &operator&=(value_t mask) {
  79. this->ashare &= mask;
  80. return *this;
  81. }
  82. inline RegAS operator&(value_t mask) const {
  83. RegAS res = *this;
  84. res &= mask;
  85. return res;
  86. }
  87. };
  88. inline value_t combine(const RegAS &A, const RegAS &B,
  89. nbits_t nbits = VALUE_BITS) {
  90. value_t mask = ~0;
  91. if (nbits < VALUE_BITS) {
  92. mask = (value_t(1)<<nbits)-1;
  93. }
  94. return (A.ashare + B.ashare) & mask;
  95. }
  96. // The type of a register holding a bit share
  97. struct RegBS {
  98. bit_t bshare;
  99. RegBS() : bshare(0) {}
  100. inline bit_t share() const { return bshare; }
  101. inline void set(bit_t s) { bshare = s; }
  102. // Set each side's share to a random bit
  103. inline void randomize() {
  104. unsigned char randb;
  105. arc4random_buf(&randb, sizeof(randb));
  106. bshare = randb & 1;
  107. }
  108. inline RegBS &operator^=(const RegBS &rhs) {
  109. this->bshare ^= rhs.bshare;
  110. return *this;
  111. }
  112. inline RegBS operator^(const RegBS &rhs) const {
  113. RegBS res = *this;
  114. res ^= rhs;
  115. return res;
  116. }
  117. inline RegBS &operator^=(const bit_t &rhs) {
  118. this->bshare ^= rhs;
  119. return *this;
  120. }
  121. inline RegBS operator^(const bit_t &rhs) const {
  122. RegBS res = *this;
  123. res ^= rhs;
  124. return res;
  125. }
  126. };
  127. // The type of a register holding an XOR share of a value
  128. struct RegXS {
  129. value_t xshare;
  130. RegXS() : xshare(0) {}
  131. RegXS(const RegBS &b) { xshare = b.bshare ? ~0 : 0; }
  132. inline value_t share() const { return xshare; }
  133. inline void set(value_t s) { xshare = s; }
  134. // Set each side's share to a random value nbits bits long
  135. inline void randomize(size_t nbits = VALUE_BITS) {
  136. value_t mask = MASKBITS(nbits);
  137. arc4random_buf(&xshare, sizeof(xshare));
  138. xshare &= mask;
  139. }
  140. // For RegXS, + and * should be interpreted bitwise; that is, + is
  141. // really XOR and * is really AND. - is also XOR (the same as +).
  142. // We also include actual XOR operators for convenience
  143. inline RegXS &operator+=(const RegXS &rhs) {
  144. this->xshare ^= rhs.xshare;
  145. return *this;
  146. }
  147. inline RegXS operator+(const RegXS &rhs) const {
  148. RegXS res = *this;
  149. res += rhs;
  150. return res;
  151. }
  152. inline RegXS &operator-=(const RegXS &rhs) {
  153. this->xshare ^= rhs.xshare;
  154. return *this;
  155. }
  156. inline RegXS operator-(const RegXS &rhs) const {
  157. RegXS res = *this;
  158. res -= rhs;
  159. return res;
  160. }
  161. inline RegXS operator-() const {
  162. RegXS res = *this;
  163. return res;
  164. }
  165. inline RegXS &operator*=(value_t rhs) {
  166. this->xshare &= rhs;
  167. return *this;
  168. }
  169. inline RegXS operator*(value_t rhs) const {
  170. RegXS res = *this;
  171. res *= rhs;
  172. return res;
  173. }
  174. inline RegXS &operator^=(const RegXS &rhs) {
  175. this->xshare ^= rhs.xshare;
  176. return *this;
  177. }
  178. inline RegXS operator^(const RegXS &rhs) const {
  179. RegXS res = *this;
  180. res ^= rhs;
  181. return res;
  182. }
  183. inline RegXS &operator&=(value_t mask) {
  184. this->xshare &= mask;
  185. return *this;
  186. }
  187. inline RegXS operator&(value_t mask) const {
  188. RegXS res = *this;
  189. res &= mask;
  190. return res;
  191. }
  192. // Extract a bit share of bit bitnum of the XOR-shared register
  193. inline RegBS bit(nbits_t bitnum) const {
  194. RegBS bs;
  195. bs.bshare = !!(xshare & (value_t(1)<<bitnum));
  196. return bs;
  197. }
  198. };
  199. inline value_t combine(const RegXS &A, const RegXS &B,
  200. nbits_t nbits = VALUE_BITS) {
  201. value_t mask = ~0;
  202. if (nbits < VALUE_BITS) {
  203. mask = (value_t(1)<<nbits)-1;
  204. }
  205. return (A.xshare ^ B.xshare) & mask;
  206. }
  207. // Some useful operations on tuples of the above types
  208. template <typename T>
  209. std::tuple<T,T> operator+=(std::tuple<T,T> &A,
  210. const std::tuple<T,T> &B)
  211. {
  212. std::get<0>(A) += std::get<0>(B);
  213. std::get<1>(A) += std::get<1>(B);
  214. return A;
  215. }
  216. template <typename T>
  217. std::tuple<T,T> operator+=(const std::tuple<T&,T&> &A,
  218. const std::tuple<T,T> &B)
  219. {
  220. std::get<0>(A) += std::get<0>(B);
  221. std::get<1>(A) += std::get<1>(B);
  222. return A;
  223. }
  224. template <typename T>
  225. std::tuple<T,T> operator+(const std::tuple<T,T> &A,
  226. const std::tuple<T,T> &B)
  227. {
  228. auto res = A;
  229. res += B;
  230. return res;
  231. }
  232. template <typename T>
  233. std::tuple<T,T> operator-=(const std::tuple<T&,T&> &A,
  234. const std::tuple<T,T> &B)
  235. {
  236. std::get<0>(A) -= std::get<0>(B);
  237. std::get<1>(A) -= std::get<1>(B);
  238. return A;
  239. }
  240. template <typename T>
  241. std::tuple<T,T> operator-=(std::tuple<T,T> &A,
  242. const std::tuple<T,T> &B)
  243. {
  244. std::get<0>(A) -= std::get<0>(B);
  245. std::get<1>(A) -= std::get<1>(B);
  246. return A;
  247. }
  248. template <typename T>
  249. std::tuple<T,T> operator-(const std::tuple<T,T> &A,
  250. const std::tuple<T,T> &B)
  251. {
  252. auto res = A;
  253. res -= B;
  254. return res;
  255. }
  256. template <typename T>
  257. std::tuple<T,T> operator*=(const std::tuple<T&,T&> &A,
  258. const std::tuple<value_t,value_t> &B)
  259. {
  260. std::get<0>(A) *= std::get<0>(B);
  261. std::get<1>(A) *= std::get<1>(B);
  262. return A;
  263. }
  264. template <typename T>
  265. std::tuple<T,T> operator*=(std::tuple<T,T> &A,
  266. const std::tuple<value_t,value_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<value_t,value_t> &B)
  275. {
  276. auto res = A;
  277. res *= B;
  278. return res;
  279. }
  280. template <typename T>
  281. inline std::tuple<value_t,value_t> combine(
  282. const std::tuple<T,T> &A, const std::tuple<T,T> &B,
  283. nbits_t nbits = VALUE_BITS) {
  284. return std::make_tuple(
  285. combine(std::get<0>(A), std::get<0>(B), nbits),
  286. combine(std::get<1>(A), std::get<1>(B), nbits));
  287. }
  288. template <typename T>
  289. std::tuple<T,T,T> operator+=(const std::tuple<T&,T&,T&> &A,
  290. const std::tuple<T,T,T> &B)
  291. {
  292. std::get<0>(A) += std::get<0>(B);
  293. std::get<1>(A) += std::get<1>(B);
  294. std::get<2>(A) += std::get<2>(B);
  295. return A;
  296. }
  297. template <typename T>
  298. std::tuple<T,T,T> operator+=(std::tuple<T,T,T> &A,
  299. const std::tuple<T,T,T> &B)
  300. {
  301. std::get<0>(A) += std::get<0>(B);
  302. std::get<1>(A) += std::get<1>(B);
  303. std::get<2>(A) += std::get<2>(B);
  304. return A;
  305. }
  306. template <typename T>
  307. std::tuple<T,T,T> operator+(const std::tuple<T,T,T> &A,
  308. const std::tuple<T,T,T> &B)
  309. {
  310. auto res = A;
  311. res += B;
  312. return res;
  313. }
  314. template <typename T>
  315. std::tuple<T,T,T> operator-=(const std::tuple<T&,T&,T&> &A,
  316. const std::tuple<T,T,T> &B)
  317. {
  318. std::get<0>(A) -= std::get<0>(B);
  319. std::get<1>(A) -= std::get<1>(B);
  320. std::get<2>(A) -= std::get<2>(B);
  321. return A;
  322. }
  323. template <typename T>
  324. std::tuple<T,T,T> operator-=(std::tuple<T,T,T> &A,
  325. const std::tuple<T,T,T> &B)
  326. {
  327. std::get<0>(A) -= std::get<0>(B);
  328. std::get<1>(A) -= std::get<1>(B);
  329. std::get<2>(A) -= std::get<2>(B);
  330. return A;
  331. }
  332. template <typename T>
  333. std::tuple<T,T,T> operator-(const std::tuple<T,T,T> &A,
  334. const std::tuple<T,T,T> &B)
  335. {
  336. auto res = A;
  337. res -= B;
  338. return res;
  339. }
  340. template <typename T>
  341. std::tuple<T,T,T> operator*=(const std::tuple<T&,T&,T&> &A,
  342. const std::tuple<value_t,value_t,value_t> &B)
  343. {
  344. std::get<0>(A) *= std::get<0>(B);
  345. std::get<1>(A) *= std::get<1>(B);
  346. std::get<2>(A) *= std::get<2>(B);
  347. return A;
  348. }
  349. template <typename T>
  350. std::tuple<T,T,T> operator*=(std::tuple<T,T,T> &A,
  351. const std::tuple<value_t,value_t,value_t> &B)
  352. {
  353. std::get<0>(A) *= std::get<0>(B);
  354. std::get<1>(A) *= std::get<1>(B);
  355. std::get<2>(A) *= std::get<2>(B);
  356. return A;
  357. }
  358. template <typename T>
  359. std::tuple<T,T,T> operator*(const std::tuple<T,T,T> &A,
  360. const std::tuple<value_t,value_t,value_t> &B)
  361. {
  362. auto res = A;
  363. res *= B;
  364. return res;
  365. }
  366. template <typename T>
  367. inline std::tuple<value_t,value_t,value_t> combine(
  368. const std::tuple<T,T,T> &A, const std::tuple<T,T,T> &B,
  369. nbits_t nbits = VALUE_BITS) {
  370. return std::make_tuple(
  371. combine(std::get<0>(A), std::get<0>(B), nbits),
  372. combine(std::get<1>(A), std::get<1>(B), nbits),
  373. combine(std::get<2>(A), std::get<2>(B), nbits));
  374. }
  375. // The _maximum_ number of bits in an MPC address; the actual size of
  376. // the memory will typically be set at runtime, but it cannot exceed
  377. // this value. It is more efficient (in terms of communication) in some
  378. // places for this value to be at most 32.
  379. #ifndef ADDRESS_MAX_BITS
  380. #define ADDRESS_MAX_BITS 32
  381. #endif
  382. // Addresses of MPC secret-shared memory are of this type
  383. #if ADDRESS_MAX_BITS <= 32
  384. using address_t = uint32_t;
  385. #elif ADDRESS_MAX_BITS <= 64
  386. using address_t = uint64_t;
  387. #else
  388. #error "Unsupported value of ADDRESS_MAX_BITS"
  389. #endif
  390. #if ADDRESS_MAX_BITS > VALUE_BITS
  391. #error "VALUE_BITS must be at least as large as ADDRESS_MAX_BITS"
  392. #endif
  393. // A multiplication triple is a triple (X0,Y0,Z0) held by P0 (and
  394. // correspondingly (X1,Y1,Z1) held by P1), with all values random,
  395. // but subject to the relation that X0*Y1 + Y0*X1 = Z0+Z1
  396. using MultTriple = std::tuple<value_t, value_t, value_t>;
  397. // The *Name structs are a way to get strings representing the names of
  398. // the types as would be given to preprocessing to create them in
  399. // advance.
  400. struct MultTripleName { static constexpr const char *name = "t"; };
  401. // A half-triple is (X0,Z0) held by P0 (and correspondingly (Y1,Z1) held
  402. // by P1), with all values random, but subject to the relation that
  403. // X0*Y1 = Z0+Z1
  404. using HalfTriple = std::tuple<value_t, value_t>;
  405. struct HalfTripleName { static constexpr const char *name = "h"; };
  406. // The type of nodes in a DPF. This must be at least as many bits as
  407. // the security parameter, and at least twice as many bits as value_t.
  408. using DPFnode = __m128i;
  409. // A Select triple is a triple of (X0,Y0,Z0) where X0 is a bit and Y0
  410. // and Z0 are DPFnodes held by P0 (and correspondingly (X1,Y1,Z1) held
  411. // by P1), with all values random, but subject to the relation that
  412. // (X0*Y1) ^ (Y0*X1) = Z0^Z1. These are only used while creating RDPFs
  413. // in the preprocessing phase, so we never need to store them. This is
  414. // a struct instead of a tuple for alignment reasons.
  415. struct SelectTriple {
  416. bit_t X;
  417. DPFnode Y, Z;
  418. };
  419. // These are defined in rdpf.hpp, but declared here to avoid cyclic
  420. // header dependencies.
  421. struct RDPFPair;
  422. struct RDPFPairName { static constexpr const char *name = "r"; };
  423. struct RDPFTriple;
  424. struct RDPFTripleName { static constexpr const char *name = "r"; };
  425. struct CDPF;
  426. struct CDPFName { static constexpr const char *name = "c"; };
  427. // We want the I/O (using << and >>) for many classes
  428. // to just be a common thing: write out the bytes
  429. // straight from memory
  430. #define DEFAULT_IO(CLASSNAME) \
  431. template <typename T> \
  432. T& operator>>(T& is, CLASSNAME &x) \
  433. { \
  434. is.read((char *)&x, sizeof(x)); \
  435. return is; \
  436. } \
  437. \
  438. template <typename T> \
  439. T& operator<<(T& os, const CLASSNAME &x) \
  440. { \
  441. os.write((const char *)&x, sizeof(x)); \
  442. return os; \
  443. }
  444. // Default I/O for various types
  445. DEFAULT_IO(DPFnode)
  446. DEFAULT_IO(RegBS)
  447. DEFAULT_IO(RegAS)
  448. DEFAULT_IO(RegXS)
  449. DEFAULT_IO(MultTriple)
  450. DEFAULT_IO(HalfTriple)
  451. // And for pairs and triples
  452. #define DEFAULT_TUPLE_IO(CLASSNAME) \
  453. template <typename T> \
  454. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME> &x) \
  455. { \
  456. is >> std::get<0>(x) >> std::get<1>(x); \
  457. return is; \
  458. } \
  459. \
  460. template <typename T> \
  461. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME> &x) \
  462. { \
  463. os << std::get<0>(x) << std::get<1>(x); \
  464. return os; \
  465. } \
  466. \
  467. template <typename T> \
  468. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  469. { \
  470. is >> std::get<0>(x) >> std::get<1>(x) >> std::get<2>(x); \
  471. return is; \
  472. } \
  473. \
  474. template <typename T> \
  475. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  476. { \
  477. os << std::get<0>(x) << std::get<1>(x) << std::get<2>(x); \
  478. return os; \
  479. }
  480. DEFAULT_TUPLE_IO(RegAS)
  481. DEFAULT_TUPLE_IO(RegXS)
  482. enum ProcessingMode {
  483. MODE_ONLINE, // Online mode, after preprocessing has been done
  484. MODE_PREPROCESSING, // Preprocessing mode
  485. MODE_ONLINEONLY // Online-only mode, where all computations are
  486. }; // done online
  487. #endif