11//! Adapters for OT types.
22
33use bitvec:: { order:: Lsb0 , vec:: BitVec } ;
4+ use cryprot_core:: { Block , buf:: Buf } ;
5+ use cryprot_net:: ConnectionError ;
46use futures:: { SinkExt , StreamExt } ;
7+ use subtle:: ConditionallySelectable ;
8+ use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
59
6- use crate :: { Connected , RandChoiceRotReceiver , RandChoiceRotSender , RotReceiver , RotSender } ;
10+ use crate :: {
11+ Connected , CotReceiver , CotSender , Malicious , RandChoiceRotReceiver , RandChoiceRotSender ,
12+ RotReceiver , RotSender , SemiHonest ,
13+ } ;
714
815/// Adapts a [`RandChoiceRotReceiver`] into a [`RotReceiver`] and
916/// [`RandChoiceRotSender`] into [`RotSender`].
@@ -26,13 +33,18 @@ impl<P: Connected> Connected for ChosenChoice<P> {
2633 }
2734}
2835
36+ impl < P : SemiHonest > SemiHonest for ChosenChoice < P > { }
37+
38+ // TODO is there something I can cite that this holds?
39+ impl < P : Malicious > Malicious for ChosenChoice < P > { }
40+
2941impl < R : RandChoiceRotReceiver > RotReceiver for ChosenChoice < R > {
3042 type Error = R :: Error ;
3143
3244 async fn receive_into (
3345 & mut self ,
34- choices : & [ subtle:: Choice ] ,
3546 ots : & mut impl cryprot_core:: buf:: Buf < cryprot_core:: Block > ,
47+ choices : & [ subtle:: Choice ] ,
3648 ) -> Result < ( ) , Self :: Error > {
3749 let mut rand_choices = self
3850 . 0
@@ -72,6 +84,171 @@ impl<S: RotSender + RandChoiceRotSender + Send> RotSender for ChosenChoice<S> {
7284 }
7385}
7486
87+ /// Adapts any [`RotSender`]/[`RotReceiver`] into a
88+ /// [`CotSender`]/[`CotReceiver`].
89+ ///
90+ /// This adapter can also be used to easily implement the correlated OT traits
91+ /// on the protocol types directly. Because `&mut S: RotSender` when `S:
92+ /// RotSender` you can create a temporary [`CorrelatedFromRandom`] from a `&mut
93+ /// self` inside an implementation of the correlated traits.
94+ ///
95+ /// ```
96+ /// use cryprot_core::{Block, buf::Buf};
97+ ///
98+ /// use cryprot_ot::adapter::CorrelatedFromRandom;
99+ /// use cryprot_ot::{Connected, CotSender, RotSender};
100+ ///
101+ /// struct MyRotSender;
102+ ///
103+ /// # impl Connected for MyRotSender {
104+ /// # fn connection(&mut self) -> &mut cryprot_net::Connection {
105+ /// # todo!()
106+ /// # }
107+ /// # }
108+ ///
109+ /// // Error type must implement `From<ConnectionError>` and `From<io::Error>` for
110+ /// // adapter
111+ /// #[derive(thiserror::Error, Debug)]
112+ /// enum Error {
113+ /// #[error("connection")]
114+ /// Connection(#[from] cryprot_net::ConnectionError),
115+ /// #[error("io")]
116+ /// Io(#[from] std::io::Error),
117+ /// }
118+ ///
119+ /// impl RotSender for MyRotSender {
120+ /// type Error = Error;
121+ ///
122+ /// async fn send_into(
123+ /// &mut self,
124+ /// ots: &mut impl cryprot_core::buf::Buf<[cryprot_core::Block; 2]>,
125+ /// ) -> Result<(), Self::Error> {
126+ /// todo!()
127+ /// }
128+ /// }
129+ ///
130+ /// impl CotSender for MyRotSender {
131+ /// type Error = <MyRotSender as RotSender>::Error;
132+ ///
133+ /// async fn correlated_send_into<B, F>(
134+ /// &mut self,
135+ /// ots: &mut B,
136+ /// correlation: F,
137+ /// ) -> Result<(), Self::Error>
138+ /// where
139+ /// B: Buf<Block>,
140+ /// F: FnMut(usize) -> Block + Send,
141+ /// {
142+ /// // because &mut self also implements RotSender, we can use it for the adapter
143+ /// CorrelatedFromRandom::new(self)
144+ /// .correlated_send_into(ots, correlation)
145+ /// .await
146+ /// }
147+ /// }
148+ /// ```
149+ #[ derive( Debug ) ]
150+ pub struct CorrelatedFromRandom < P > ( P ) ;
151+
152+ impl < P > CorrelatedFromRandom < P > {
153+ pub fn new ( protocol : P ) -> Self {
154+ Self ( protocol)
155+ }
156+ }
157+
158+ impl < P : Connected > Connected for CorrelatedFromRandom < P > {
159+ fn connection ( & mut self ) -> & mut cryprot_net:: Connection {
160+ self . 0 . connection ( )
161+ }
162+ }
163+
164+ impl < P : SemiHonest > SemiHonest for CorrelatedFromRandom < P > { }
165+
166+ // TODO is there something I can cite that this holds?
167+ impl < P : Malicious > Malicious for CorrelatedFromRandom < P > { }
168+
169+ // should fit in one jumbo frame
170+ const COR_CHUNK_SIZE : usize = 8500 / Block :: BYTES ;
171+
172+ impl < S : RotSender > CotSender for CorrelatedFromRandom < S >
173+ where
174+ S :: Error : From < ConnectionError > + From < std:: io:: Error > ,
175+ {
176+ type Error = S :: Error ;
177+
178+ async fn correlated_send_into < B , F > (
179+ & mut self ,
180+ ots : & mut B ,
181+ mut correlation : F ,
182+ ) -> Result < ( ) , Self :: Error >
183+ where
184+ B : Buf < Block > ,
185+ F : FnMut ( usize ) -> Block + Send ,
186+ {
187+ let mut r_ots: B :: BufKind < [ Block ; 2 ] > = B :: BufKind :: zeroed ( ots. len ( ) ) ;
188+ self . 0 . send_into ( & mut r_ots) . await ?;
189+ let mut send_buf: Vec < Block > = Vec :: zeroed ( COR_CHUNK_SIZE ) ;
190+ let ( mut tx, _) = self . connection ( ) . byte_stream ( ) . await ?;
191+ // Using spawn_compute here results in slightly lower performance.
192+ // I think there is just not enough work done per byte transmitted here.
193+ // This implementation is also simpler and less prone to errors than the
194+ // spawn_compute one.
195+ for ( chunk_idx, ( ot_chunk, rot_chunk) ) in ots
196+ . chunks_mut ( send_buf. len ( ) )
197+ . zip ( r_ots. chunks ( send_buf. len ( ) ) )
198+ . enumerate ( )
199+ {
200+ for ( idx, ( ( ot, r_ot) , correction) ) in ot_chunk
201+ . iter_mut ( )
202+ . zip ( rot_chunk)
203+ . zip ( & mut send_buf)
204+ . enumerate ( )
205+ {
206+ * ot = r_ot[ 0 ] ;
207+ * correction = r_ot[ 1 ] ^ r_ot[ 0 ] ^ correlation ( chunk_idx * COR_CHUNK_SIZE + idx) ;
208+ }
209+ tx. write_all ( bytemuck:: must_cast_slice_mut (
210+ & mut send_buf[ ..ot_chunk. len ( ) ] ,
211+ ) )
212+ . await ?;
213+ }
214+ Ok ( ( ) )
215+ }
216+ }
217+
218+ impl < R : RotReceiver > CotReceiver for CorrelatedFromRandom < R >
219+ where
220+ R :: Error : From < ConnectionError > + From < std:: io:: Error > ,
221+ {
222+ type Error = R :: Error ;
223+
224+ async fn correlated_receive_into < B > (
225+ & mut self ,
226+ ots : & mut B ,
227+ choices : & [ subtle:: Choice ] ,
228+ ) -> Result < ( ) , Self :: Error >
229+ where
230+ B : Buf < Block > ,
231+ {
232+ self . 0 . receive_into ( ots, choices) . await ?;
233+ let mut recv_buf: Vec < Block > = Vec :: zeroed ( COR_CHUNK_SIZE ) ;
234+ let ( _, mut rx) = self . connection ( ) . byte_stream ( ) . await ?;
235+ for ( ot_chunk, choice_chunk) in ots
236+ . chunks_mut ( COR_CHUNK_SIZE )
237+ . zip ( choices. chunks ( COR_CHUNK_SIZE ) )
238+ {
239+ rx. read_exact ( bytemuck:: must_cast_slice_mut (
240+ & mut recv_buf[ ..ot_chunk. len ( ) ] ,
241+ ) )
242+ . await ?;
243+ for ( ( ot, correction) , choice) in ot_chunk. iter_mut ( ) . zip ( & recv_buf) . zip ( choice_chunk) {
244+ let use_correction = Block :: conditional_select ( & Block :: ZERO , & Block :: ONES , * choice) ;
245+ * ot ^= use_correction & * correction;
246+ }
247+ }
248+ Ok ( ( ) )
249+ }
250+ }
251+
75252#[ cfg( test) ]
76253mod tests {
77254 use cryprot_net:: testing:: { init_tracing, local_conn} ;
0 commit comments