1use super::mut_only::MutOnly;
2use super::{
3 ClientHello, GetSessionPendingError, PrivateKeyMethod, PrivateKeyMethodError, SelectCertError,
4 Ssl, SslAlert, SslContextBuilder, SslRef, SslSession, SslSignatureAlgorithm, SslVerifyError,
5 SslVerifyMode,
6};
7use crate::ex_data::Index;
8use once_cell::sync::Lazy;
9use std::convert::identity;
10use std::future::Future;
11use std::pin::Pin;
12use std::task::{ready, Context, Poll, Waker};
13
14pub type BoxSelectCertFuture = ExDataFuture<Result<BoxSelectCertFinish, AsyncSelectCertError>>;
16
17pub type BoxSelectCertFinish = Box<dyn FnOnce(ClientHello<'_>) -> Result<(), AsyncSelectCertError>>;
19
20pub type BoxPrivateKeyMethodFuture =
22 ExDataFuture<Result<BoxPrivateKeyMethodFinish, AsyncPrivateKeyMethodError>>;
23
24pub type BoxPrivateKeyMethodFinish =
26 Box<dyn FnOnce(&mut SslRef, &mut [u8]) -> Result<usize, AsyncPrivateKeyMethodError>>;
27
28pub type BoxGetSessionFuture = ExDataFuture<Option<BoxGetSessionFinish>>;
30
31pub type BoxGetSessionFinish = Box<dyn FnOnce(&mut SslRef, &[u8]) -> Option<SslSession>>;
33
34pub type BoxCustomVerifyFuture = ExDataFuture<Result<BoxCustomVerifyFinish, SslAlert>>;
36
37pub type BoxCustomVerifyFinish = Box<dyn FnOnce(&mut SslRef) -> Result<(), SslAlert>>;
39
40pub type ExDataFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
44
45pub(crate) static TASK_WAKER_INDEX: Lazy<Index<Ssl, Option<Waker>>> =
46 Lazy::new(|| Ssl::new_ex_index().unwrap());
47pub(crate) static SELECT_CERT_FUTURE_INDEX: Lazy<Index<Ssl, MutOnly<Option<BoxSelectCertFuture>>>> =
48 Lazy::new(|| Ssl::new_ex_index().unwrap());
49pub(crate) static SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX: Lazy<
50 Index<Ssl, MutOnly<Option<BoxPrivateKeyMethodFuture>>>,
51> = Lazy::new(|| Ssl::new_ex_index().unwrap());
52pub(crate) static SELECT_GET_SESSION_FUTURE_INDEX: Lazy<
53 Index<Ssl, MutOnly<Option<BoxGetSessionFuture>>>,
54> = Lazy::new(|| Ssl::new_ex_index().unwrap());
55pub(crate) static SELECT_CUSTOM_VERIFY_FUTURE_INDEX: Lazy<
56 Index<Ssl, MutOnly<Option<BoxCustomVerifyFuture>>>,
57> = Lazy::new(|| Ssl::new_ex_index().unwrap());
58
59impl SslContextBuilder {
60 pub fn set_async_select_certificate_callback<F>(&mut self, callback: F)
74 where
75 F: Fn(&mut ClientHello<'_>) -> Result<BoxSelectCertFuture, AsyncSelectCertError>
76 + Send
77 + Sync
78 + 'static,
79 {
80 self.set_select_certificate_callback(move |mut client_hello| {
81 let fut_poll_result = with_ex_data_future(
82 &mut client_hello,
83 *SELECT_CERT_FUTURE_INDEX,
84 ClientHello::ssl_mut,
85 &callback,
86 identity,
87 );
88
89 let fut_result = match fut_poll_result {
90 Poll::Ready(fut_result) => fut_result,
91 Poll::Pending => return Err(SelectCertError::RETRY),
92 };
93
94 let finish = fut_result.or(Err(SelectCertError::ERROR))?;
95
96 finish(client_hello).or(Err(SelectCertError::ERROR))
97 })
98 }
99
100 pub fn set_async_private_key_method(&mut self, method: impl AsyncPrivateKeyMethod) {
107 self.set_private_key_method(AsyncPrivateKeyMethodBridge(Box::new(method)));
108 }
109
110 pub unsafe fn set_async_get_session_callback<F>(&mut self, callback: F)
127 where
128 F: Fn(&mut SslRef, &[u8]) -> Option<BoxGetSessionFuture> + Send + Sync + 'static,
129 {
130 let async_callback = move |ssl: &mut SslRef, id: &[u8]| {
131 let fut_poll_result = with_ex_data_future(
132 &mut *ssl,
133 *SELECT_GET_SESSION_FUTURE_INDEX,
134 |ssl| ssl,
135 |ssl| callback(ssl, id).ok_or(()),
136 |option| option.ok_or(()),
137 );
138
139 match fut_poll_result {
140 Poll::Ready(Err(())) => Ok(None),
141 Poll::Ready(Ok(finish)) => Ok(finish(ssl, id)),
142 Poll::Pending => Err(GetSessionPendingError),
143 }
144 };
145
146 self.set_get_session_callback(async_callback)
147 }
148
149 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
166 where
167 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
168 {
169 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback))
170 }
171}
172
173impl SslRef {
174 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
175 where
176 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
177 {
178 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback))
179 }
180
181 pub fn set_task_waker(&mut self, waker: Option<Waker>) {
183 self.replace_ex_data(*TASK_WAKER_INDEX, waker);
184 }
185}
186
187fn async_custom_verify_callback<F>(
188 callback: F,
189) -> impl Fn(&mut SslRef) -> Result<(), SslVerifyError>
190where
191 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
192{
193 move |ssl| {
194 let fut_poll_result = with_ex_data_future(
195 &mut *ssl,
196 *SELECT_CUSTOM_VERIFY_FUTURE_INDEX,
197 |ssl| ssl,
198 &callback,
199 identity,
200 );
201
202 match fut_poll_result {
203 Poll::Ready(Err(alert)) => Err(SslVerifyError::Invalid(alert)),
204 Poll::Ready(Ok(finish)) => Ok(finish(ssl).map_err(SslVerifyError::Invalid)?),
205 Poll::Pending => Err(SslVerifyError::Retry),
206 }
207 }
208}
209
210#[derive(Debug, Copy, Clone, PartialEq, Eq)]
212pub struct AsyncSelectCertError;
213
214pub trait AsyncPrivateKeyMethod: Send + Sync + 'static {
222 fn sign(
230 &self,
231 ssl: &mut SslRef,
232 input: &[u8],
233 signature_algorithm: SslSignatureAlgorithm,
234 output: &mut [u8],
235 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
236
237 fn decrypt(
245 &self,
246 ssl: &mut SslRef,
247 input: &[u8],
248 output: &mut [u8],
249 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
250}
251
252#[derive(Debug, Copy, Clone, PartialEq, Eq)]
254pub struct AsyncPrivateKeyMethodError;
255
256struct AsyncPrivateKeyMethodBridge(Box<dyn AsyncPrivateKeyMethod>);
257
258impl PrivateKeyMethod for AsyncPrivateKeyMethodBridge {
259 fn sign(
260 &self,
261 ssl: &mut SslRef,
262 input: &[u8],
263 signature_algorithm: SslSignatureAlgorithm,
264 output: &mut [u8],
265 ) -> Result<usize, PrivateKeyMethodError> {
266 with_private_key_method(ssl, output, |ssl, output| {
267 <dyn AsyncPrivateKeyMethod>::sign(&*self.0, ssl, input, signature_algorithm, output)
268 })
269 }
270
271 fn decrypt(
272 &self,
273 ssl: &mut SslRef,
274 input: &[u8],
275 output: &mut [u8],
276 ) -> Result<usize, PrivateKeyMethodError> {
277 with_private_key_method(ssl, output, |ssl, output| {
278 <dyn AsyncPrivateKeyMethod>::decrypt(&*self.0, ssl, input, output)
279 })
280 }
281
282 fn complete(
283 &self,
284 ssl: &mut SslRef,
285 output: &mut [u8],
286 ) -> Result<usize, PrivateKeyMethodError> {
287 with_private_key_method(ssl, output, |_, _| {
288 if cfg!(debug_assertions) {
293 panic!("BUG: boring called complete without a pending operation");
294 }
295
296 Err(AsyncPrivateKeyMethodError)
297 })
298 }
299}
300
301fn with_private_key_method(
308 ssl: &mut SslRef,
309 output: &mut [u8],
310 create_fut: impl FnOnce(
311 &mut SslRef,
312 &mut [u8],
313 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>,
314) -> Result<usize, PrivateKeyMethodError> {
315 let fut_poll_result = with_ex_data_future(
316 ssl,
317 *SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX,
318 |ssl| ssl,
319 |ssl| create_fut(ssl, output),
320 identity,
321 );
322
323 let fut_result = match fut_poll_result {
324 Poll::Ready(fut_result) => fut_result,
325 Poll::Pending => return Err(PrivateKeyMethodError::RETRY),
326 };
327
328 let finish = fut_result.or(Err(PrivateKeyMethodError::FAILURE))?;
329
330 finish(ssl, output).or(Err(PrivateKeyMethodError::FAILURE))
331}
332
333fn with_ex_data_future<H, R, T, E>(
338 ssl_handle: &mut H,
339 index: Index<Ssl, MutOnly<Option<ExDataFuture<R>>>>,
340 get_ssl_mut: impl Fn(&mut H) -> &mut SslRef,
341 create_fut: impl FnOnce(&mut H) -> Result<ExDataFuture<R>, E>,
342 into_result: impl Fn(R) -> Result<T, E>,
343) -> Poll<Result<T, E>> {
344 let ssl = get_ssl_mut(ssl_handle);
345 let waker = ssl
346 .ex_data(*TASK_WAKER_INDEX)
347 .cloned()
348 .flatten()
349 .expect("task waker should be set");
350
351 let mut ctx = Context::from_waker(&waker);
352
353 if let Some(data @ Some(_)) = ssl.ex_data_mut(index).map(MutOnly::get_mut) {
354 let fut_result = into_result(ready!(data.as_mut().unwrap().as_mut().poll(&mut ctx)));
355
356 *data = None;
357
358 Poll::Ready(fut_result)
359 } else {
360 let mut fut = create_fut(ssl_handle)?;
361
362 match fut.as_mut().poll(&mut ctx) {
363 Poll::Ready(fut_result) => Poll::Ready(into_result(fut_result)),
364 Poll::Pending => {
365 get_ssl_mut(ssl_handle).replace_ex_data(index, MutOnly::new(Some(fut)));
366
367 Poll::Pending
368 }
369 }
370 }
371}