client.rs 10 KB

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