1use super::mut_only::MutOnly;
2use super::{
3 ClientHello, GetSessionPendingError, PrivateKeyMethod, PrivateKeyMethodError, SelectCertError,
4 Ssl, SslAlert, SslContextBuilder, SslRef, SslSession, SslSignatureAlgorithm, SslVerifyError,
5 SslVerifyMode,
6};
7#[cfg(feature = "credential")]
8use crate::error::ErrorStack;
9use crate::ex_data::Index;
10#[cfg(feature = "credential")]
11use crate::ssl::SslCredentialBuilder;
12use std::convert::identity;
13use std::future::Future;
14use std::pin::Pin;
15use std::sync::LazyLock;
16use std::task::{ready, Context, Poll, Waker};
17
18pub type BoxSelectCertFuture = ExDataFuture<Result<BoxSelectCertFinish, AsyncSelectCertError>>;
20
21pub type BoxSelectCertFinish = Box<dyn FnOnce(ClientHello<'_>) -> Result<(), AsyncSelectCertError>>;
23
24pub type BoxPrivateKeyMethodFuture =
26 ExDataFuture<Result<BoxPrivateKeyMethodFinish, AsyncPrivateKeyMethodError>>;
27
28pub type BoxPrivateKeyMethodFinish =
30 Box<dyn FnOnce(&mut SslRef, &mut [u8]) -> Result<usize, AsyncPrivateKeyMethodError>>;
31
32pub 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>>;
40
41pub type BoxCustomVerifyFinish = Box<dyn FnOnce(&mut SslRef) -> Result<(), SslAlert>>;
43
44pub type ExDataFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
48
49pub(crate) static TASK_WAKER_INDEX: LazyLock<Index<Ssl, Option<Waker>>> =
50 LazyLock::new(|| Ssl::new_ex_index().unwrap());
51pub(crate) static SELECT_CERT_FUTURE_INDEX: LazyLock<
52 Index<Ssl, MutOnly<Option<BoxSelectCertFuture>>>,
53> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
54pub(crate) static SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX: LazyLock<
55 Index<Ssl, MutOnly<Option<BoxPrivateKeyMethodFuture>>>,
56> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
57pub(crate) static SELECT_GET_SESSION_FUTURE_INDEX: LazyLock<
58 Index<Ssl, MutOnly<Option<BoxGetSessionFuture>>>,
59> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
60pub(crate) static SELECT_CUSTOM_VERIFY_FUTURE_INDEX: LazyLock<
61 Index<Ssl, MutOnly<Option<BoxCustomVerifyFuture>>>,
62> = LazyLock::new(|| Ssl::new_ex_index().unwrap());
63
64impl SslContextBuilder {
65 pub fn set_async_select_certificate_callback<F>(&mut self, callback: F)
79 where
80 F: Fn(&mut ClientHello<'_>) -> Result<BoxSelectCertFuture, AsyncSelectCertError>
81 + Send
82 + Sync
83 + 'static,
84 {
85 self.set_select_certificate_callback(move |mut client_hello| {
86 let fut_poll_result = with_ex_data_future(
87 &mut client_hello,
88 *SELECT_CERT_FUTURE_INDEX,
89 ClientHello::ssl_mut,
90 &callback,
91 identity,
92 );
93
94 let fut_result = match fut_poll_result {
95 Poll::Ready(fut_result) => fut_result,
96 Poll::Pending => return Err(SelectCertError::RETRY),
97 };
98
99 let finish = fut_result.or(Err(SelectCertError::ERROR))?;
100
101 finish(client_hello).or(Err(SelectCertError::ERROR))
102 });
103 }
104
105 pub fn set_async_private_key_method(&mut self, method: impl AsyncPrivateKeyMethod) {
112 self.set_private_key_method(AsyncPrivateKeyMethodBridge(Box::new(method)));
113 }
114
115 pub unsafe fn set_async_get_session_callback<F>(&mut self, callback: F)
132 where
133 F: Fn(&mut SslRef, &[u8]) -> Option<BoxGetSessionFuture> + Send + Sync + 'static,
134 {
135 let async_callback = move |ssl: &mut SslRef, id: &[u8]| {
136 let fut_poll_result = with_ex_data_future(
137 &mut *ssl,
138 *SELECT_GET_SESSION_FUTURE_INDEX,
139 |ssl| ssl,
140 |ssl| callback(ssl, id).ok_or(()),
141 |option| option.ok_or(()),
142 );
143
144 match fut_poll_result {
145 Poll::Ready(Err(())) => Ok(None),
146 Poll::Ready(Ok(finish)) => Ok(finish(ssl, id)),
147 Poll::Pending => Err(GetSessionPendingError),
148 }
149 };
150
151 self.set_get_session_callback(async_callback);
152 }
153
154 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
171 where
172 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
173 {
174 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback));
175 }
176}
177
178#[cfg(feature = "credential")]
179impl SslCredentialBuilder {
180 pub fn set_async_private_key_method(
187 &mut self,
188 method: impl AsyncPrivateKeyMethod,
189 ) -> Result<(), ErrorStack> {
190 self.set_private_key_method(AsyncPrivateKeyMethodBridge(Box::new(method)))
191 }
192}
193
194impl SslRef {
195 pub fn set_async_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
196 where
197 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
198 {
199 self.set_custom_verify_callback(mode, async_custom_verify_callback(callback));
200 }
201
202 pub fn set_task_waker(&mut self, waker: Option<Waker>) {
204 self.replace_ex_data(*TASK_WAKER_INDEX, waker);
205 }
206}
207
208fn async_custom_verify_callback<F>(
209 callback: F,
210) -> impl Fn(&mut SslRef) -> Result<(), SslVerifyError>
211where
212 F: Fn(&mut SslRef) -> Result<BoxCustomVerifyFuture, SslAlert> + Send + Sync + 'static,
213{
214 move |ssl| {
215 let fut_poll_result = with_ex_data_future(
216 &mut *ssl,
217 *SELECT_CUSTOM_VERIFY_FUTURE_INDEX,
218 |ssl| ssl,
219 &callback,
220 identity,
221 );
222
223 match fut_poll_result {
224 Poll::Ready(Err(alert)) => Err(SslVerifyError::Invalid(alert)),
225 Poll::Ready(Ok(finish)) => Ok(finish(ssl).map_err(SslVerifyError::Invalid)?),
226 Poll::Pending => Err(SslVerifyError::Retry),
227 }
228 }
229}
230
231#[derive(Debug, Copy, Clone, PartialEq, Eq)]
233pub struct AsyncSelectCertError;
234
235pub trait AsyncPrivateKeyMethod: Send + Sync + 'static {
243 fn sign(
251 &self,
252 ssl: &mut SslRef,
253 input: &[u8],
254 signature_algorithm: SslSignatureAlgorithm,
255 output: &mut [u8],
256 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
257
258 fn decrypt(
266 &self,
267 ssl: &mut SslRef,
268 input: &[u8],
269 output: &mut [u8],
270 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>;
271}
272
273#[derive(Debug, Copy, Clone, PartialEq, Eq)]
275pub struct AsyncPrivateKeyMethodError;
276
277struct AsyncPrivateKeyMethodBridge(Box<dyn AsyncPrivateKeyMethod>);
278
279impl PrivateKeyMethod for AsyncPrivateKeyMethodBridge {
280 fn sign(
281 &self,
282 ssl: &mut SslRef,
283 input: &[u8],
284 signature_algorithm: SslSignatureAlgorithm,
285 output: &mut [u8],
286 ) -> Result<usize, PrivateKeyMethodError> {
287 with_private_key_method(ssl, output, |ssl, output| {
288 <dyn AsyncPrivateKeyMethod>::sign(&*self.0, ssl, input, signature_algorithm, output)
289 })
290 }
291
292 fn decrypt(
293 &self,
294 ssl: &mut SslRef,
295 input: &[u8],
296 output: &mut [u8],
297 ) -> Result<usize, PrivateKeyMethodError> {
298 with_private_key_method(ssl, output, |ssl, output| {
299 <dyn AsyncPrivateKeyMethod>::decrypt(&*self.0, ssl, input, output)
300 })
301 }
302
303 fn complete(
304 &self,
305 ssl: &mut SslRef,
306 output: &mut [u8],
307 ) -> Result<usize, PrivateKeyMethodError> {
308 with_private_key_method(ssl, output, |_, _| {
309 if cfg!(debug_assertions) {
314 panic!("BUG: boring called complete without a pending operation");
315 }
316
317 Err(AsyncPrivateKeyMethodError)
318 })
319 }
320}
321
322fn with_private_key_method(
329 ssl: &mut SslRef,
330 output: &mut [u8],
331 create_fut: impl FnOnce(
332 &mut SslRef,
333 &mut [u8],
334 ) -> Result<BoxPrivateKeyMethodFuture, AsyncPrivateKeyMethodError>,
335) -> Result<usize, PrivateKeyMethodError> {
336 let fut_poll_result = with_ex_data_future(
337 ssl,
338 *SELECT_PRIVATE_KEY_METHOD_FUTURE_INDEX,
339 |ssl| ssl,
340 |ssl| create_fut(ssl, output),
341 identity,
342 );
343
344 let fut_result = match fut_poll_result {
345 Poll::Ready(fut_result) => fut_result,
346 Poll::Pending => return Err(PrivateKeyMethodError::RETRY),
347 };
348
349 let finish = fut_result.or(Err(PrivateKeyMethodError::FAILURE))?;
350
351 finish(ssl, output).or(Err(PrivateKeyMethodError::FAILURE))
352}
353
354fn with_ex_data_future<H, R, T, E>(
359 ssl_handle: &mut H,
360 index: Index<Ssl, MutOnly<Option<ExDataFuture<R>>>>,
361 get_ssl_mut: impl Fn(&mut H) -> &mut SslRef,
362 create_fut: impl FnOnce(&mut H) -> Result<ExDataFuture<R>, E>,
363 into_result: impl Fn(R) -> Result<T, E>,
364) -> Poll<Result<T, E>> {
365 let ssl = get_ssl_mut(ssl_handle);
366 let waker = ssl
367 .ex_data(*TASK_WAKER_INDEX)
368 .cloned()
369 .flatten()
370 .expect("task waker should be set");
371
372 let mut ctx = Context::from_waker(&waker);
373
374 if let Some(data @ Some(_)) = ssl.ex_data_mut(index).map(MutOnly::get_mut) {
375 let fut_result = into_result(ready!(data.as_mut().unwrap().as_mut().poll(&mut ctx)));
376
377 *data = None;
378
379 Poll::Ready(fut_result)
380 } else {
381 let mut fut = create_fut(ssl_handle)?;
382
383 match fut.as_mut().poll(&mut ctx) {
384 Poll::Ready(fut_result) => Poll::Ready(into_result(fut_result)),
385 Poll::Pending => {
386 get_ssl_mut(ssl_handle).replace_ex_data(index, MutOnly::new(Some(fut)));
387
388 Poll::Pending
389 }
390 }
391 }
392}