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