Skip to main content

wasmtime_wasi_tls/
lib.rs

1//! # Wasmtime's [wasi-tls] (Transport Layer Security) Implementation
2//!
3//! This crate provides the Wasmtime host implementation for the [wasi-tls] API.
4//! The [wasi-tls] world allows WebAssembly modules to perform SSL/TLS operations,
5//! such as establishing secure connections to servers. TLS often relies on other wasi networking systems
6//! to provide the stream so it will be common to enable the [wasi:cli] world as well with the networking features enabled.
7//!
8//! # An example of how to configure [wasi-tls] is the following:
9//!
10//! ```rust
11//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
12//! use wasmtime::{
13//!     component::{Linker, ResourceTable},
14//!     Store, Engine, Result,
15//! };
16//! use wasmtime_wasi_tls::{WasiTlsCtx, WasiTlsCtxBuilder, WasiTlsView, WasiTlsCtxView};
17//! use wasmtime_wasi_tls::p2::LinkOptions;
18//!
19//! struct Ctx {
20//!     table: ResourceTable,
21//!     wasi_ctx: WasiCtx,
22//!     wasi_tls_ctx: WasiTlsCtx,
23//! }
24//!
25//! impl WasiView for Ctx {
26//!     fn ctx(&mut self) -> WasiCtxView<'_> {
27//!         WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }
28//!     }
29//! }
30//!
31//! impl WasiTlsView for Ctx {
32//!     fn tls(&mut self) -> WasiTlsCtxView<'_> {
33//!         WasiTlsCtxView { ctx: &mut self.wasi_tls_ctx, table: &mut self.table }
34//!     }
35//! }
36//!
37//! #[tokio::main]
38//! async fn main() -> Result<()> {
39//!     let ctx = Ctx {
40//!         table: ResourceTable::new(),
41//!         wasi_ctx: WasiCtx::builder()
42//!             .inherit_stderr()
43//!             .inherit_network()
44//!             .allow_ip_name_lookup(true)
45//!             .build(),
46//!         wasi_tls_ctx: WasiTlsCtxBuilder::new()
47//!             // Optionally, configure a specific TLS provider:
48//!             // .provider(Box::new(wasmtime_wasi_tls::RustlsProvider::default()))
49//!             // .provider(Box::new(wasmtime_wasi_tls::NativeTlsProvider::default()))
50//!             // .provider(Box::new(wasmtime_wasi_tls::OpenSslProvider::default()))
51//!             .build(),
52//!     };
53//!
54//!     let engine = Engine::default();
55//!
56//!     // Set up wasi-cli
57//!     let mut store = Store::new(&engine, ctx);
58//!     let mut linker: Linker<Ctx> = Linker::new(&engine);
59//!     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
60//!
61//!     // Add wasi-tls types and turn on the feature in linker
62//!     let mut opts = LinkOptions::default();
63//!     opts.tls(true);
64//!     wasmtime_wasi_tls::p2::add_to_linker(&mut linker, &opts)?;
65//!
66//!     // ... use `linker` to instantiate within `store` ...
67//!     Ok(())
68//! }
69//!
70//! ```
71//! [wasi-tls]: https://github.com/WebAssembly/wasi-tls
72//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest
73
74#![deny(missing_docs)]
75#![doc(test(attr(deny(warnings))))]
76#![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]
77
78use tokio::io::{AsyncRead, AsyncWrite};
79mod error;
80mod providers;
81
82/// WASIp2 (`wasi:tls@0.2.0-draft`) host implementation.
83#[cfg(feature = "p2")]
84pub mod p2;
85/// WASIp3 (`wasi:tls@0.3.0-draft`) host implementation.
86#[cfg(feature = "p3")]
87pub mod p3;
88
89pub use error::Error;
90pub use providers::*;
91
92#[cfg(any(feature = "p2", feature = "p3"))]
93use wasmtime::component::{HasData, ResourceTable};
94
95/// Builder-style structure used to create a [`WasiTlsCtx`].
96#[cfg(any(feature = "p2", feature = "p3"))]
97pub struct WasiTlsCtxBuilder {
98    provider: Box<dyn TlsProvider>,
99}
100#[cfg(any(feature = "p2", feature = "p3"))]
101impl WasiTlsCtxBuilder {
102    /// Creates a builder for a new context with default parameters set.
103    pub fn new() -> Self {
104        Default::default()
105    }
106
107    /// Configure the TLS provider to use for this context.
108    ///
109    /// By default, this is set to the [`DefaultProvider`] which is picked at
110    /// compile time based on feature flags. If this crate is compiled with
111    /// multiple TLS providers, this method can be used to specify the provider
112    /// at runtime.
113    pub fn provider(mut self, provider: Box<dyn TlsProvider>) -> Self {
114        self.provider = provider;
115        self
116    }
117
118    /// Uses the configured context so far to construct the final [`WasiTlsCtx`].
119    pub fn build(self) -> WasiTlsCtx {
120        WasiTlsCtx {
121            provider: self.provider,
122        }
123    }
124}
125#[cfg(any(feature = "p2", feature = "p3"))]
126impl Default for WasiTlsCtxBuilder {
127    fn default() -> Self {
128        Self {
129            provider: Box::new(DefaultProvider::default()),
130        }
131    }
132}
133
134/// Wasi TLS context needed for internal `wasi-tls` state.
135#[cfg(any(feature = "p2", feature = "p3"))]
136pub struct WasiTlsCtx {
137    pub(crate) provider: Box<dyn TlsProvider>,
138}
139
140/// The type for which this crate implements the `wasi:tls` interfaces.
141#[cfg(any(feature = "p2", feature = "p3"))]
142pub(crate) struct WasiTls;
143#[cfg(any(feature = "p2", feature = "p3"))]
144impl HasData for WasiTls {
145    type Data<'a> = WasiTlsCtxView<'a>;
146}
147
148/// View into [`WasiTlsCtx`] implementation and [`ResourceTable`].
149#[cfg(any(feature = "p2", feature = "p3"))]
150pub struct WasiTlsCtxView<'a> {
151    /// Mutable reference to table used to manage resources.
152    pub table: &'a mut ResourceTable,
153
154    /// Mutable reference to the WASI TLS context.
155    pub ctx: &'a mut WasiTlsCtx,
156}
157
158/// A trait which provides internal WASI TLS state.
159#[cfg(any(feature = "p2", feature = "p3"))]
160pub trait WasiTlsView: Send {
161    /// Return a [`WasiTlsCtxView`] from mutable reference to self.
162    fn tls(&mut self) -> WasiTlsCtxView<'_>;
163}
164
165/// The data stream that carries the encrypted TLS data.
166/// Typically this is a TCP stream.
167pub trait TlsTransport: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
168impl<T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized + 'static> TlsTransport for T {}
169
170/// A TLS connection.
171pub trait TlsStream: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
172
173/// A TLS implementation.
174pub trait TlsProvider: Send + Sync + 'static {
175    /// Set up a client TLS connection using the provided `server_name` and `transport`.
176    fn connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream;
177}
178
179pub(crate) type BoxFutureTlsStream =
180    std::pin::Pin<Box<dyn Future<Output = Result<Box<dyn TlsStream>, Error>> + Send>>;