client.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. use rand::rngs::ThreadRng;
  2. use rand::RngCore;
  3. use std::collections::VecDeque;
  4. use std::mem;
  5. use std::os::raw::c_uchar;
  6. use std::sync::mpsc::*;
  7. use std::thread::*;
  8. use aes::Block;
  9. use rayon::prelude::*;
  10. use subtle::Choice;
  11. use curve25519_dalek::ristretto::RistrettoPoint;
  12. use curve25519_dalek::scalar::Scalar;
  13. use crate::ot::*;
  14. use crate::params;
  15. use crate::to_vecdata;
  16. use crate::DbEntry;
  17. use crate::PreProcSingleMsg;
  18. use crate::PreProcSingleRespMsg;
  19. use crate::VecData;
  20. enum Command {
  21. PreProc(usize),
  22. PreProcFinish(Vec<PreProcSingleRespMsg>),
  23. Query(usize),
  24. }
  25. enum Response {
  26. PubParams(Vec<u8>),
  27. PreProcMsg(Vec<u8>),
  28. PreProcDone,
  29. QueryMsg(Vec<u8>),
  30. }
  31. // The internal client state for a single outstanding preprocess query
  32. struct PreProcOutSingleState {
  33. rand_idx: usize,
  34. ot_state: Vec<(Choice, Scalar)>,
  35. }
  36. // The internal client state for a single preprocess ready to be used
  37. struct PreProcSingleState {
  38. rand_idx: usize,
  39. ot_key: Block,
  40. }
  41. pub struct Client {
  42. r: usize,
  43. thread_handle: JoinHandle<()>,
  44. incoming_cmd: SyncSender<Command>,
  45. outgoing_resp: Receiver<Response>,
  46. }
  47. impl Client {
  48. pub fn new(r: usize) -> (Self, Vec<u8>) {
  49. let (incoming_cmd, incoming_cmd_recv) = sync_channel(0);
  50. let (outgoing_resp_send, outgoing_resp) = sync_channel(0);
  51. let thread_handle = spawn(move || {
  52. let spiral_params = params::get_spiral_params(r);
  53. let mut clientrng = rand::thread_rng();
  54. let mut rng = rand::thread_rng();
  55. let mut spiral_client = spiral_rs::client::Client::init(&spiral_params, &mut clientrng);
  56. let num_records = 1 << r;
  57. let num_records_mask = num_records - 1;
  58. let spiral_blocking_factor = spiral_params.db_item_size / mem::size_of::<DbEntry>();
  59. // The first communication is the pub_params
  60. let pub_params = spiral_client.generate_keys().serialize();
  61. outgoing_resp_send
  62. .send(Response::PubParams(pub_params))
  63. .unwrap();
  64. // State for outstanding preprocessing queries
  65. let mut preproc_out_state: Vec<PreProcOutSingleState> = Vec::new();
  66. // State for preprocessing queries ready to be used
  67. let mut preproc_state: VecDeque<PreProcSingleState> = VecDeque::new();
  68. // State for outstanding active queries
  69. let mut query_state: VecDeque<PreProcSingleState> = VecDeque::new();
  70. // Wait for commands
  71. loop {
  72. match incoming_cmd_recv.recv() {
  73. Err(_) => break,
  74. Ok(Command::PreProc(num_preproc)) => {
  75. // Ensure we don't already have outstanding
  76. // preprocessing state
  77. assert!(preproc_out_state.len() == 0);
  78. let mut preproc_msg: Vec<PreProcSingleMsg> = Vec::new();
  79. for _ in 0..num_preproc {
  80. let rand_idx = (rng.next_u64() as usize) & num_records_mask;
  81. let rand_pir_idx = rand_idx / spiral_blocking_factor;
  82. let spc_query = spiral_client.generate_query(rand_pir_idx).serialize();
  83. let (ot_state, ot_query) = otkey_request(rand_idx, r);
  84. preproc_out_state.push(PreProcOutSingleState { rand_idx, ot_state });
  85. preproc_msg.push(PreProcSingleMsg {
  86. ot_query,
  87. spc_query,
  88. });
  89. }
  90. let ret: Vec<u8> = bincode::serialize(&preproc_msg).unwrap();
  91. outgoing_resp_send.send(Response::PreProcMsg(ret)).unwrap();
  92. }
  93. Ok(Command::PreProcFinish(srvresp)) => {
  94. let num_preproc = srvresp.len();
  95. assert!(preproc_out_state.len() == num_preproc);
  96. let mut newstate: VecDeque<PreProcSingleState> = preproc_out_state
  97. .into_par_iter()
  98. .zip(srvresp)
  99. .map(|(c, s)| {
  100. let ot_key = otkey_receive(c.ot_state, &s.ot_resp);
  101. PreProcSingleState {
  102. rand_idx: c.rand_idx,
  103. ot_key,
  104. }
  105. })
  106. .collect();
  107. preproc_state.append(&mut newstate);
  108. preproc_out_state = Vec::new();
  109. outgoing_resp_send.send(Response::PreProcDone).unwrap();
  110. }
  111. Ok(Command::Query(idx)) => {
  112. // panic if there are no preproc states
  113. // available
  114. let nextstate = preproc_state.pop_front().unwrap();
  115. let offset = (num_records + nextstate.rand_idx - idx) & num_records_mask;
  116. let mut querymsg: Vec<u8> = Vec::new();
  117. querymsg.extend(idx.to_le_bytes());
  118. query_state.push_back(nextstate);
  119. outgoing_resp_send
  120. .send(Response::QueryMsg(querymsg))
  121. .unwrap();
  122. }
  123. _ => panic!("Received something unexpected in client loop"),
  124. }
  125. }
  126. });
  127. let pub_params = match outgoing_resp.recv() {
  128. Ok(Response::PubParams(x)) => x,
  129. _ => panic!("Received something unexpected in client new"),
  130. };
  131. (
  132. Client {
  133. r,
  134. thread_handle,
  135. incoming_cmd,
  136. outgoing_resp,
  137. },
  138. pub_params,
  139. )
  140. }
  141. pub fn preproc(&self, num_preproc: usize) -> Vec<u8> {
  142. self.incoming_cmd
  143. .send(Command::PreProc(num_preproc))
  144. .unwrap();
  145. let ret = match self.outgoing_resp.recv() {
  146. Ok(Response::PreProcMsg(x)) => x,
  147. _ => panic!("Received something unexpected in preproc"),
  148. };
  149. ret
  150. }
  151. pub fn preproc_finish(&self, msg: &[u8]) {
  152. self.incoming_cmd
  153. .send(Command::PreProcFinish(bincode::deserialize(msg).unwrap()))
  154. .unwrap();
  155. match self.outgoing_resp.recv() {
  156. Ok(Response::PreProcDone) => (),
  157. _ => panic!("Received something unexpected in preproc_finish"),
  158. }
  159. }
  160. pub fn query(&self, idx: usize) -> Vec<u8> {
  161. self.incoming_cmd.send(Command::Query(idx)).unwrap();
  162. let ret = match self.outgoing_resp.recv() {
  163. Ok(Response::QueryMsg(x)) => x,
  164. _ => panic!("Received something unexpected in preproc"),
  165. };
  166. ret
  167. }
  168. }
  169. #[repr(C)]
  170. pub struct ClientNewRet {
  171. client: *mut Client,
  172. pub_params: VecData,
  173. }
  174. #[no_mangle]
  175. pub extern "C" fn spir_client_new(r: u8) -> ClientNewRet {
  176. let (client, pub_params) = Client::new(r as usize);
  177. ClientNewRet {
  178. client: Box::into_raw(Box::new(client)),
  179. pub_params: to_vecdata(pub_params),
  180. }
  181. }
  182. #[no_mangle]
  183. pub extern "C" fn spir_client_free(client: *mut Client) {
  184. if client.is_null() {
  185. return;
  186. }
  187. unsafe {
  188. Box::from_raw(client);
  189. }
  190. }
  191. #[no_mangle]
  192. pub extern "C" fn spir_client_preproc(clientptr: *mut Client, num_preproc: u32) -> VecData {
  193. let client = unsafe {
  194. assert!(!clientptr.is_null());
  195. &mut *clientptr
  196. };
  197. let retvec = client.preproc(num_preproc as usize);
  198. to_vecdata(retvec)
  199. }
  200. #[no_mangle]
  201. pub extern "C" fn spir_client_preproc_finish(
  202. clientptr: *mut Client,
  203. msgdata: *const c_uchar,
  204. msglen: usize,
  205. ) {
  206. let client = unsafe {
  207. assert!(!clientptr.is_null());
  208. &mut *clientptr
  209. };
  210. let msg_slice = unsafe {
  211. assert!(!msgdata.is_null());
  212. std::slice::from_raw_parts(msgdata, msglen)
  213. };
  214. client.preproc_finish(&msg_slice);
  215. }
  216. #[no_mangle]
  217. pub extern "C" fn spir_client_query(clientptr: *mut Client, idx: usize) -> VecData {
  218. let client = unsafe {
  219. assert!(!clientptr.is_null());
  220. &mut *clientptr
  221. };
  222. let retvec = client.query(idx);
  223. to_vecdata(retvec)
  224. }