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>>;
18
19pub type BoxSelectCertFinish = Box<dyn FnOnce(ClientHello<'_>) -> Result<(), AsyncSelectCertError>>;
21
22pub type BoxPrivateKeyMethodFuture =
24 ExDataFuture<Result<BoxPrivateKeyMethodFinish, AsyncPrivateKeyMethodError>>;
25
26pub type BoxPrivateKeyMethodFinish =
28 Box<dyn FnOnce(&mut SslRef, &mut [u8]) -> Result<usize, AsyncPrivateKeyMethodError>>;
29
30pub type BoxGetSessionFuture = ExDataFuture<Option<BoxGetSessionFinish>>;
34
35pub type BoxGetSessionFinish = Box<dyn FnOnce(&mut SslRef, &[u8]) -> Option<SslSession>>;
37
38pub type BoxCustomVerifyFuture = ExDataFuture<Result<BoxCustomVerifyFinish, SslAlert>>;
42
43pub type BoxCustomVerifyFinish = Box<dyn FnOnce(&mut SslRef) -> Result<(), SslAlert>>;
45
46pub type ExDataFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
52
53pub(crate) static TASK_WAKER_INDEX: LazyLock<Index<Ssl, Option<Waker>>> =
54 LazyLock::new(|| Ssl::new_ex_index().unwrap());
55pub(crate) static SELECT_CERT_FUTURE_INDEX: LazyLock<
56 Index<Ssl, MutOnly<Option<BoxSelectCertFuture>>>,
57> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
58pub(crate) static SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX: LazyLock<
59 Index<Ssl, MutOnly<Option<BoxPrivateKeyMethodFuture>>>,
60> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
61pub(crate) static SELECT_GET_SESSION_FUTURE_INDEX: LazyLock<
62 Index<Ssl, MutOnly<Option<BoxGetSessionFuture>>>,
63> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
64pub(crate) static SELECT_CUSTOM_VERIFY_FUTURE_INDEX: LazyLock<
65 Index<Ssl, MutOnly<Option<BoxCustomVerifyFuture>>>,
66> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
67
68impl SslContextBuilder {
69 pub fn set_async_select_certificate_callback<F>(&mut self, callback: F)
83 where
84 F: Fn(&mut ClientHello<'_>) -> Result<BoxSelectCertFuture, AsyncSelectCertError>
85 + Send
86 + Sync
87 + 'static,
88 {
89 self.set_select_certificate_callback(move |mut client_hello| {
90 let fut_poll_result = with_ex_data_future(
91 &mut client_hello,
92 *SELECT_CERT_FUTURE_INDEX,
93 ClientHello::ssl_mut,
94 &callback,
95 identity,
96 );
97
98 let fut_result = match fut_poll_result {
99 Poll::Ready(fut_result) => fut_result,
100 Poll::Pending => return Err(SelectCertError::RETRY),
101 };
102
103 let finish = fut_result.or(Err(SelectCertError::ERROR))?;
104
105 finish(client_hello).or(Err(SelectCertError::ERROR))
106 })
107 }
108
109 pub fn set_async_private_key_method(&mut self, method: impl AsyncPrivateKeyMethod) {
116 self.set_private_key_method(AsyncPrivateKeyMethodBridge(Box::new(method)));
117 }
118
119 pub unsafe fn set_async_get_session_callback<F>(&mut self, callback: F)
138 where
139 F: Fn(&mut SslRef, &[u8]) -> Option<BoxGetSessionFuture> + Send + Sync + 'static,
140 {
141 let async_callback = move |ssl: &mut SslRef, id: &[u8]| {
142 let fut_poll_result = with_ex_data_future(
143 &mut *ssl,
144 *SELECT_GET_SESSION_FUTURE_INDEX,
145 |ssl| ssl,
146 |ssl| callback(ssl, id).ok_or(()),
147 |option| option.ok_or(()),
148 );
149
150 match fut_poll_result {
151 Poll::Ready(Err(())) => Ok(None),
152 Poll::Ready(Ok(finish)) => Ok(finish(ssl, id)),
153 Poll::Pending => Err(GetSessionPendingError),
154 }
155 };
156
157 self.set_get_session_callback(async_callback)
158 }
159
160 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
177 where
178 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
179 {
180 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback))
181 }
182}
183
184impl SslRef {
185 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
186 where
187 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
188 {
189 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback))
190 }
191
192 pub fn set_task_waker(&mut self, waker: Option<Waker>) {
194 self.replace_ex_data(*TASK_WAKER_INDEX, waker);
195 }
196}
197
198fn async_custom_verify_callback<F>(
199 callback: F,
200) -> impl Fn(&mut SslRef) -> Result<(), SslVerifyError>
201where
202 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
203{
204 move |ssl| {
205 let fut_poll_result = with_ex_data_future(
206 &mut *ssl,
207 *SELECT_CUSTOM_VERIFY_FUTURE_INDEX,
208 |ssl| ssl,
209 &callback,
210 identity,
211 );
212
213 match fut_poll_result {
214 Poll::Ready(Err(alert)) => Err(SslVerifyError::Invalid(alert)),
215 Poll::Ready(Ok(finish)) => Ok(finish(ssl).map_err(SslVerifyError::Invalid)?),
216 Poll::Pending => Err(SslVerifyError::Retry),
217 }
218 }
219}
220
221#[derive(Debug, Copy, Clone, PartialEq, Eq)]
223pub struct AsyncSelectCertError;
224
225pub trait AsyncPrivateKeyMethod: Send + Sync + 'static {
233 fn sign(
241 &self,
242 ssl: &mut SslRef,
243 input: &[u8],
244 signature_algorithm: SslSignatureAlgorithm,
245 output: &mut [u8],
246 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
247
248 fn decrypt(
256 &self,
257 ssl: &mut SslRef,
258 input: &[u8],
259 output: &mut [u8],
260 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
261}
262
263#[derive(Debug, Copy, Clone, PartialEq, Eq)]
265pub struct AsyncPrivateKeyMethodError;
266
267struct AsyncPrivateKeyMethodBridge(Box<dyn AsyncPrivateKeyMethod>);
268
269impl PrivateKeyMethod for AsyncPrivateKeyMethodBridge {
270 fn sign(
271 &self,
272 ssl: &mut SslRef,
273 input: &[u8],
274 signature_algorithm: SslSignatureAlgorithm,
275 output: &mut [u8],
276 ) -> Result<usize, PrivateKeyMethodError> {
277 with_private_key_method(ssl, output, |ssl, output| {
278 <dyn AsyncPrivateKeyMethod>::sign(&*self.0, ssl, input, signature_algorithm, output)
279 })
280 }
281
282 fn decrypt(
283 &self,
284 ssl: &mut SslRef,
285 input: &[u8],
286 output: &mut [u8],
287 ) -> Result<usize, PrivateKeyMethodError> {
288 with_private_key_method(ssl, output, |ssl, output| {
289 <dyn AsyncPrivateKeyMethod>::decrypt(&*self.0, ssl, input, output)
290 })
291 }
292
293 fn complete(
294 &self,
295 ssl: &mut SslRef,
296 output: &mut [u8],
297 ) -> Result<usize, PrivateKeyMethodError> {
298 with_private_key_method(ssl, output, |_, _| {
299 if cfg!(debug_assertions) {
304 panic!("BUG: boring called complete without a pending operation");
305 }
306
307 Err(AsyncPrivateKeyMethodError)
308 })
309 }
310}
311
312fn with_private_key_method(
319 ssl: &mut SslRef,
320 output: &mut [u8],
321 create_fut: impl FnOnce(
322 &mut SslRef,
323 &mut [u8],
324 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>,
325) -> Result<usize, PrivateKeyMethodError> {
326 let fut_poll_result = with_ex_data_future(
327 ssl,
328 *SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX,
329 |ssl| ssl,
330 |ssl| create_fut(ssl, output),
331 identity,
332 );
333
334 let fut_result = match fut_poll_result {
335 Poll::Ready(fut_result) => fut_result,
336 Poll::Pending => return Err(PrivateKeyMethodError::RETRY),
337 };
338
339 let finish = fut_result.or(Err(PrivateKeyMethodError::FAILURE))?;
340
341 finish(ssl, output).or(Err(PrivateKeyMethodError::FAILURE))
342}
343
344fn with_ex_data_future<H, R, T, E>(
349 ssl_handle: &mut H,
350 index: Index<Ssl, MutOnly<Option<ExDataFuture<R>>>>,
351 get_ssl_mut: impl Fn(&mut H) -> &mut SslRef,
352 create_fut: impl FnOnce(&mut H) -> Result<ExDataFuture<R>, E>,
353 into_result: impl Fn(R) -> Result<T, E>,
354) -> Poll<Result<T, E>> {
355 let ssl = get_ssl_mut(ssl_handle);
356 let waker = ssl
357 .ex_data(*TASK_WAKER_INDEX)
358 .cloned()
359 .flatten()
360 .expect("task waker should be set");
361
362 let mut ctx = Context::from_waker(&waker);
363
364 if let Some(data @ Some(_)) = ssl.ex_data_mut(index).map(MutOnly::get_mut) {
365 let fut_result = into_result(ready!(data.as_mut().unwrap().as_mut().poll(&mut ctx)));
366
367 *data = None;
368
369 Poll::Ready(fut_result)
370 } else {
371 let mut fut = create_fut(ssl_handle)?;
372
373 match fut.as_mut().poll(&mut ctx) {
374 Poll::Ready(fut_result) => Poll::Ready(into_result(fut_result)),
375 Poll::Pending => {
376 get_ssl_mut(ssl_handle).replace_ex_data(index, MutOnly::new(Some(fut)));
377
378 Poll::Pending
379 }
380 }
381 }
382}