types.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. // Set each side's share to a random value nbits bits long
  40. inline void randomize(size_t nbits = VALUE_BITS) {
  41. value_t mask = MASKBITS(nbits);
  42. arc4random_buf(&ashare, sizeof(ashare));
  43. ashare &= mask;
  44. }
  45. inline RegAS &operator+=(const RegAS &rhs) {
  46. this->ashare += rhs.ashare;
  47. return *this;
  48. }
  49. inline RegAS operator+(const RegAS &rhs) const {
  50. RegAS res = *this;
  51. res += rhs;
  52. return res;
  53. }
  54. inline RegAS &operator-=(const RegAS &rhs) {
  55. this->ashare -= rhs.ashare;
  56. return *this;
  57. }
  58. inline RegAS operator-(const RegAS &rhs) const {
  59. RegAS res = *this;
  60. res -= rhs;
  61. return res;
  62. }
  63. inline RegAS &operator*=(value_t rhs) {
  64. this->ashare *= rhs;
  65. return *this;
  66. }
  67. inline RegAS operator*(value_t rhs) const {
  68. RegAS res = *this;
  69. res *= rhs;
  70. return res;
  71. }
  72. inline RegAS &operator&=(value_t mask) {
  73. this->ashare &= mask;
  74. return *this;
  75. }
  76. inline RegAS operator&(value_t mask) const {
  77. RegAS res = *this;
  78. res &= mask;
  79. return res;
  80. }
  81. };
  82. inline value_t combine(const RegAS &A, const RegAS &B,
  83. nbits_t nbits = VALUE_BITS) {
  84. value_t mask = ~0;
  85. if (nbits < VALUE_BITS) {
  86. mask = (value_t(1)<<nbits)-1;
  87. }
  88. return (A.ashare + B.ashare) & mask;
  89. }
  90. // The type of a register holding a bit share
  91. struct RegBS {
  92. bit_t bshare;
  93. RegBS() : bshare(0) {}
  94. inline bit_t share() const { return bshare; }
  95. // Set each side's share to a random bit
  96. inline void randomize() {
  97. unsigned char randb;
  98. arc4random_buf(&randb, sizeof(randb));
  99. bshare = randb & 1;
  100. }
  101. inline RegBS &operator^=(const RegBS &rhs) {
  102. this->bshare ^= rhs.bshare;
  103. return *this;
  104. }
  105. inline RegBS operator^(const RegBS &rhs) const {
  106. RegBS res = *this;
  107. res ^= rhs;
  108. return res;
  109. }
  110. };
  111. // The type of a register holding an XOR share of a value
  112. struct RegXS {
  113. value_t xshare;
  114. RegXS() : xshare(0) {}
  115. inline value_t share() const { return xshare; }
  116. // Set each side's share to a random value nbits bits long
  117. inline void randomize(size_t nbits = VALUE_BITS) {
  118. value_t mask = MASKBITS(nbits);
  119. arc4random_buf(&xshare, sizeof(xshare));
  120. xshare &= mask;
  121. }
  122. inline RegXS &operator^=(const RegXS &rhs) {
  123. this->xshare ^= rhs.xshare;
  124. return *this;
  125. }
  126. inline RegXS operator^(const RegXS &rhs) const {
  127. RegXS res = *this;
  128. res ^= rhs;
  129. return res;
  130. }
  131. inline RegXS &operator&=(value_t mask) {
  132. this->xshare &= mask;
  133. return *this;
  134. }
  135. inline RegXS operator&(value_t mask) const {
  136. RegXS res = *this;
  137. res &= mask;
  138. return res;
  139. }
  140. // Extract a bit share of bit bitnum of the XOR-shared register
  141. inline RegBS bit(nbits_t bitnum) const {
  142. RegBS bs;
  143. bs.bshare = !!(xshare & (value_t(1)<<bitnum));
  144. return bs;
  145. }
  146. };
  147. inline value_t combine(const RegXS &A, const RegXS &B,
  148. nbits_t nbits = VALUE_BITS) {
  149. value_t mask = ~0;
  150. if (nbits < VALUE_BITS) {
  151. mask = (value_t(1)<<nbits)-1;
  152. }
  153. return (A.xshare ^ B.xshare) & mask;
  154. }
  155. // Some useful operations on tuples of the above types
  156. template <typename T>
  157. std::tuple<T,T> operator+=(std::tuple<T,T> &A,
  158. const std::tuple<T,T> &B)
  159. {
  160. std::get<0>(A) += std::get<0>(B);
  161. std::get<1>(A) += std::get<1>(B);
  162. return A;
  163. }
  164. template <typename T>
  165. std::tuple<T,T> operator+=(const std::tuple<T&,T&> &A,
  166. const std::tuple<T,T> &B)
  167. {
  168. std::get<0>(A) += std::get<0>(B);
  169. std::get<1>(A) += std::get<1>(B);
  170. return A;
  171. }
  172. template <typename T>
  173. std::tuple<T,T> operator+(const std::tuple<T,T> &A,
  174. const std::tuple<T,T> &B)
  175. {
  176. auto res = A;
  177. res += B;
  178. return res;
  179. }
  180. template <typename T>
  181. std::tuple<T,T> operator-=(const std::tuple<T&,T&> &A,
  182. const std::tuple<T,T> &B)
  183. {
  184. std::get<0>(A) -= std::get<0>(B);
  185. std::get<1>(A) -= std::get<1>(B);
  186. return A;
  187. }
  188. template <typename T>
  189. std::tuple<T,T> operator-=(std::tuple<T,T> &A,
  190. const std::tuple<T,T> &B)
  191. {
  192. std::get<0>(A) -= std::get<0>(B);
  193. std::get<1>(A) -= std::get<1>(B);
  194. return A;
  195. }
  196. template <typename T>
  197. std::tuple<T,T> operator-(const std::tuple<T,T> &A,
  198. const std::tuple<T,T> &B)
  199. {
  200. auto res = A;
  201. res -= B;
  202. return res;
  203. }
  204. template <typename T>
  205. std::tuple<T,T> operator*=(const std::tuple<T&,T&> &A,
  206. const std::tuple<value_t,value_t> &B)
  207. {
  208. std::get<0>(A) *= std::get<0>(B);
  209. std::get<1>(A) *= std::get<1>(B);
  210. return A;
  211. }
  212. template <typename T>
  213. std::tuple<T,T> operator*=(std::tuple<T,T> &A,
  214. const std::tuple<value_t,value_t> &B)
  215. {
  216. std::get<0>(A) *= std::get<0>(B);
  217. std::get<1>(A) *= std::get<1>(B);
  218. return A;
  219. }
  220. template <typename T>
  221. std::tuple<T,T> operator*(const std::tuple<T,T> &A,
  222. const std::tuple<value_t,value_t> &B)
  223. {
  224. auto res = A;
  225. res *= B;
  226. return res;
  227. }
  228. template <typename T>
  229. inline std::tuple<value_t,value_t> combine(
  230. const std::tuple<T,T> &A, const std::tuple<T,T> &B,
  231. nbits_t nbits = VALUE_BITS) {
  232. return std::make_tuple(
  233. combine(std::get<0>(A), std::get<0>(B), nbits),
  234. combine(std::get<1>(A), std::get<1>(B), nbits));
  235. }
  236. template <typename T>
  237. std::tuple<T,T,T> operator+=(const std::tuple<T&,T&,T&> &A,
  238. const std::tuple<T,T,T> &B)
  239. {
  240. std::get<0>(A) += std::get<0>(B);
  241. std::get<1>(A) += std::get<1>(B);
  242. std::get<2>(A) += std::get<2>(B);
  243. return A;
  244. }
  245. template <typename T>
  246. std::tuple<T,T,T> operator+=(std::tuple<T,T,T> &A,
  247. const std::tuple<T,T,T> &B)
  248. {
  249. std::get<0>(A) += std::get<0>(B);
  250. std::get<1>(A) += std::get<1>(B);
  251. std::get<2>(A) += std::get<2>(B);
  252. return A;
  253. }
  254. template <typename T>
  255. std::tuple<T,T,T> operator+(const std::tuple<T,T,T> &A,
  256. const std::tuple<T,T,T> &B)
  257. {
  258. auto res = A;
  259. res += B;
  260. return res;
  261. }
  262. template <typename T>
  263. std::tuple<T,T,T> operator-=(const std::tuple<T&,T&,T&> &A,
  264. const std::tuple<T,T,T> &B)
  265. {
  266. std::get<0>(A) -= std::get<0>(B);
  267. std::get<1>(A) -= std::get<1>(B);
  268. std::get<2>(A) -= std::get<2>(B);
  269. return A;
  270. }
  271. template <typename T>
  272. std::tuple<T,T,T> operator-=(std::tuple<T,T,T> &A,
  273. const std::tuple<T,T,T> &B)
  274. {
  275. std::get<0>(A) -= std::get<0>(B);
  276. std::get<1>(A) -= std::get<1>(B);
  277. std::get<2>(A) -= std::get<2>(B);
  278. return A;
  279. }
  280. template <typename T>
  281. std::tuple<T,T,T> operator-(const std::tuple<T,T,T> &A,
  282. const std::tuple<T,T,T> &B)
  283. {
  284. auto res = A;
  285. res -= B;
  286. return res;
  287. }
  288. template <typename T>
  289. std::tuple<T,T,T> operator*=(const std::tuple<T&,T&,T&> &A,
  290. const std::tuple<value_t,value_t,value_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<value_t,value_t,value_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<value_t,value_t,value_t> &B)
  309. {
  310. auto res = A;
  311. res *= B;
  312. return res;
  313. }
  314. template <typename T>
  315. inline std::tuple<value_t,value_t,value_t> combine(
  316. const std::tuple<T,T,T> &A, const std::tuple<T,T,T> &B,
  317. nbits_t nbits = VALUE_BITS) {
  318. return std::make_tuple(
  319. combine(std::get<0>(A), std::get<0>(B), nbits),
  320. combine(std::get<1>(A), std::get<1>(B), nbits),
  321. combine(std::get<2>(A), std::get<2>(B), nbits));
  322. }
  323. // The _maximum_ number of bits in an MPC address; the actual size of
  324. // the memory will typically be set at runtime, but it cannot exceed
  325. // this value. It is more efficient (in terms of communication) in some
  326. // places for this value to be at most 32.
  327. #ifndef ADDRESS_MAX_BITS
  328. #define ADDRESS_MAX_BITS 32
  329. #endif
  330. // Addresses of MPC secret-shared memory are of this type
  331. #if ADDRESS_MAX_BITS <= 32
  332. using address_t = uint32_t;
  333. #elif ADDRESS_MAX_BITS <= 64
  334. using address_t = uint64_t;
  335. #else
  336. #error "Unsupported value of ADDRESS_MAX_BITS"
  337. #endif
  338. #if ADDRESS_MAX_BITS > VALUE_BITS
  339. #error "VALUE_BITS must be at least as large as ADDRESS_MAX_BITS"
  340. #endif
  341. // A multiplication triple is a triple (X0,Y0,Z0) held by P0 (and
  342. // correspondingly (X1,Y1,Z1) held by P1), with all values random,
  343. // but subject to the relation that X0*Y1 + Y0*X1 = Z0+Z1
  344. using MultTriple = std::tuple<value_t, value_t, value_t>;
  345. // The *Name structs are a way to get strings representing the names of
  346. // the types as would be given to preprocessing to create them in
  347. // advance.
  348. struct MultTripleName { static constexpr const char *name = "t"; };
  349. // A half-triple is (X0,Z0) held by P0 (and correspondingly (Y1,Z1) held
  350. // by P1), with all values random, but subject to the relation that
  351. // X0*Y1 = Z0+Z1
  352. using HalfTriple = std::tuple<value_t, value_t>;
  353. struct HalfTripleName { static constexpr const char *name = "h"; };
  354. // The type of nodes in a DPF. This must be at least as many bits as
  355. // the security parameter, and at least twice as many bits as value_t.
  356. using DPFnode = __m128i;
  357. // A Select triple is a triple of (X0,Y0,Z0) where X0 is a bit and Y0
  358. // and Z0 are DPFnodes held by P0 (and correspondingly (X1,Y1,Z1) held
  359. // by P1), with all values random, but subject to the relation that
  360. // (X0*Y1) ^ (Y0*X1) = Z0^Z1. These are only used while creating RDPFs
  361. // in the preprocessing phase, so we never need to store them. This is
  362. // a struct instead of a tuple for alignment reasons.
  363. struct SelectTriple {
  364. bit_t X;
  365. DPFnode Y, Z;
  366. };
  367. // These are defined in rdpf.hpp, but declared here to avoid cyclic
  368. // header dependencies.
  369. struct RDPFPair;
  370. struct RDPFPairName { static constexpr const char *name = "r"; };
  371. struct RDPFTriple;
  372. struct RDPFTripleName { static constexpr const char *name = "r"; };
  373. // We want the I/O (using << and >>) for many classes
  374. // to just be a common thing: write out the bytes
  375. // straight from memory
  376. #define DEFAULT_IO(CLASSNAME) \
  377. template <typename T> \
  378. T& operator>>(T& is, CLASSNAME &x) \
  379. { \
  380. is.read((char *)&x, sizeof(x)); \
  381. return is; \
  382. } \
  383. \
  384. template <typename T> \
  385. T& operator<<(T& os, const CLASSNAME &x) \
  386. { \
  387. os.write((const char *)&x, sizeof(x)); \
  388. return os; \
  389. }
  390. // Default I/O for various types
  391. DEFAULT_IO(RegBS)
  392. DEFAULT_IO(RegAS)
  393. DEFAULT_IO(RegXS)
  394. DEFAULT_IO(MultTriple)
  395. DEFAULT_IO(HalfTriple)
  396. // And for pairs and triples
  397. #define DEFAULT_TUPLE_IO(CLASSNAME) \
  398. template <typename T> \
  399. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME> &x) \
  400. { \
  401. is >> std::get<0>(x) >> std::get<1>(x); \
  402. return is; \
  403. } \
  404. \
  405. template <typename T> \
  406. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME> &x) \
  407. { \
  408. os << std::get<0>(x) << std::get<1>(x); \
  409. return os; \
  410. } \
  411. \
  412. template <typename T> \
  413. T& operator>>(T& is, std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  414. { \
  415. is >> std::get<0>(x) >> std::get<1>(x) >> std::get<2>(x); \
  416. return is; \
  417. } \
  418. \
  419. template <typename T> \
  420. T& operator<<(T& os, const std::tuple<CLASSNAME, CLASSNAME, CLASSNAME> &x) \
  421. { \
  422. os << std::get<0>(x) << std::get<1>(x) << std::get<2>(x); \
  423. return os; \
  424. }
  425. DEFAULT_TUPLE_IO(RegAS)
  426. DEFAULT_TUPLE_IO(RegXS)
  427. #endif