Skip to main content

wasi_crypto_wasmtime/
lib.rs

1//! Glue that exposes the `wasi-crypto` host functions to Wasmtime, the same way
2//! Wasmtime exposes the regular preview1 WASI calls.
3//!
4//! The heavy lifting (every cryptographic primitive, every handle table) lives
5//! in the `wasi-crypto` host-functions crate, which speaks in terms of Rust
6//! slices and `u32` handles. The wasm ABI, on the other hand, speaks in terms of
7//! guest pointers and integer error codes. Wiggle bridges the two: from the
8//! witx description it generates one host trait per witx module plus a matching
9//! `add_to_linker`. All this file does is implement those traits by reading the
10//! arguments out of guest memory, calling into the `CryptoCtx`, and writing the
11//! results back.
12
13use wasi_crypto::{
14    AlgorithmType as HostAlgorithmType, CryptoCtx, CryptoError, Handle, KeyPairEncoding,
15    PublicKeyEncoding, SecretKeyEncoding, SignatureEncoding, Version,
16};
17use wiggle::{GuestError, GuestMemory, GuestPtr};
18
19/// Host state for the wasi-crypto functions. Drop this into your Wasmtime store
20/// (or expose it through a view) and hand `add_to_linker` a closure returning
21/// `&mut WasiCryptoCtx`.
22pub struct WasiCryptoCtx {
23    ctx: CryptoCtx,
24}
25
26impl Default for WasiCryptoCtx {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl WasiCryptoCtx {
33    pub fn new() -> Self {
34        Self {
35            ctx: CryptoCtx::new(),
36        }
37    }
38}
39
40/// Either something went wrong inside the cryptography layer (`CryptoError`) or
41/// while touching guest memory (`GuestError`). Both funnel into a single witx
42/// `crypto_errno` for the guest.
43#[derive(Debug, thiserror::Error)]
44pub enum WasiCryptoError {
45    #[error("crypto error: {0}")]
46    Crypto(#[from] CryptoError),
47    #[error("guest memory error: {0}")]
48    Guest(#[from] GuestError),
49}
50
51type WResult<T> = Result<T, WasiCryptoError>;
52
53mod generated {
54    use super::{WasiCryptoCtx, WasiCryptoError};
55    wiggle::from_witx!({
56        witx: ["witx/wasi_ephemeral_crypto.witx"],
57        errors: { crypto_errno => WasiCryptoError },
58    });
59
60    impl wiggle::GuestErrorType for types::CryptoErrno {
61        fn success() -> Self {
62            Self::Success
63        }
64    }
65
66    impl types::UserErrorConversion for WasiCryptoCtx {
67        fn crypto_errno_from_wasi_crypto_error(
68            &mut self,
69            e: super::WasiCryptoError,
70        ) -> wiggle::error::Result<types::CryptoErrno> {
71            Ok(super::to_errno(e))
72        }
73    }
74}
75
76pub use generated::types;
77
78/// Register the complete wasi-crypto API (all five witx modules) on a linker in
79/// one call, the same way `wasmtime_wasi::p1::add_to_linker_sync` registers WASI.
80pub fn add_to_linker<T: 'static>(
81    linker: &mut wiggle::wasmtime_crate::Linker<T>,
82    get_cx: impl Fn(&mut T) -> &mut WasiCryptoCtx + Send + Sync + Copy + 'static,
83) -> wiggle::error::Result<()> {
84    use generated::*;
85    wasi_ephemeral_crypto_common::add_to_linker(linker, get_cx)?;
86    wasi_ephemeral_crypto_asymmetric_common::add_to_linker(linker, get_cx)?;
87    wasi_ephemeral_crypto_signatures::add_to_linker(linker, get_cx)?;
88    wasi_ephemeral_crypto_symmetric::add_to_linker(linker, get_cx)?;
89    wasi_ephemeral_crypto_kx::add_to_linker(linker, get_cx)?;
90    Ok(())
91}
92
93fn to_errno(e: WasiCryptoError) -> types::CryptoErrno {
94    use types::CryptoErrno as E;
95    let crypto = match e {
96        WasiCryptoError::Crypto(c) => c,
97        // A fault while reading or writing guest memory is, from the guest's
98        // point of view, an internal inconsistency.
99        WasiCryptoError::Guest(_) => return E::GuestError,
100    };
101    match crypto {
102        CryptoError::Success => E::Success,
103        CryptoError::GuestError(_) => E::GuestError,
104        CryptoError::NotImplemented => E::NotImplemented,
105        CryptoError::UnsupportedFeature => E::UnsupportedFeature,
106        CryptoError::ProhibitedOperation => E::ProhibitedOperation,
107        CryptoError::UnsupportedEncoding => E::UnsupportedEncoding,
108        CryptoError::UnsupportedAlgorithm => E::UnsupportedAlgorithm,
109        CryptoError::UnsupportedOption => E::UnsupportedOption,
110        CryptoError::InvalidKey => E::InvalidKey,
111        CryptoError::InvalidLength => E::InvalidLength,
112        CryptoError::VerificationFailed => E::VerificationFailed,
113        CryptoError::RNGError => E::RngError,
114        CryptoError::AlgorithmFailure => E::AlgorithmFailure,
115        CryptoError::InvalidSignature => E::InvalidSignature,
116        CryptoError::Closed => E::Closed,
117        CryptoError::InvalidHandle => E::InvalidHandle,
118        CryptoError::Overflow => E::Overflow,
119        CryptoError::InternalError => E::InternalError,
120        CryptoError::TooManyHandles => E::TooManyHandles,
121        CryptoError::KeyNotSupported => E::KeyNotSupported,
122        CryptoError::KeyRequired => E::KeyRequired,
123        CryptoError::InvalidTag => E::InvalidTag,
124        CryptoError::InvalidOperation => E::InvalidOperation,
125        CryptoError::NonceRequired => E::NonceRequired,
126        CryptoError::InvalidNonce => E::InvalidNonce,
127        CryptoError::OptionNotSet => E::OptionNotSet,
128        CryptoError::NotFound => E::NotFound,
129        CryptoError::ParametersMissing => E::ParametersMissing,
130        CryptoError::IncompatibleKeys => E::IncompatibleKeys,
131        CryptoError::Expired => E::Expired,
132    }
133}
134
135// --- guest-memory helpers ---------------------------------------------------
136
137/// Read a `(pointer, len)` pair out of guest memory into an owned buffer. We
138/// copy eagerly so the immutable borrow of guest memory is released before we
139/// need to write any output back.
140fn read_bytes(mem: &GuestMemory<'_>, ptr: GuestPtr<u8>, len: types::Size) -> WResult<Vec<u8>> {
141    Ok(mem.as_cow(ptr.as_array(len))?.into_owned())
142}
143
144/// Read a guest string into an owned `String`.
145fn read_str(mem: &GuestMemory<'_>, ptr: GuestPtr<str>) -> WResult<String> {
146    Ok(mem.as_cow_str(ptr)?.into_owned())
147}
148
149/// Copy `data` into a guest `(pointer, max_len)` buffer, returning the number of
150/// bytes written. Mirrors the host contract: the guest buffer may be larger than
151/// the data, but never smaller.
152fn write_bytes(
153    mem: &mut GuestMemory<'_>,
154    ptr: GuestPtr<u8>,
155    max_len: types::Size,
156    data: &[u8],
157) -> WResult<types::Size> {
158    if data.len() > max_len as usize {
159        return Err(CryptoError::Overflow.into());
160    }
161    mem.copy_from_slice(data, ptr.as_array(data.len() as u32))?;
162    Ok(data.len() as types::Size)
163}
164
165/// Run a host operation that fills a guest `(pointer, len)` output buffer and
166/// reports how many bytes it wrote. On ordinary (unshared) memory the host
167/// writes straight into the guest's buffer; for shared memory — where we can't
168/// hand out a `&mut` view — we stage in a scratch buffer and copy. Either way the
169/// host's own bounds checks against the `len`-sized buffer apply.
170fn fill_out_buf(
171    mem: &mut GuestMemory<'_>,
172    ptr: GuestPtr<u8>,
173    len: types::Size,
174    fill: impl FnOnce(&mut [u8]) -> Result<usize, CryptoError>,
175) -> WResult<types::Size> {
176    if let Some(dst) = mem.as_slice_mut(ptr.as_array(len))? {
177        let n = fill(dst)?;
178        return Ok(n as types::Size);
179    }
180    let mut tmp = vec![0u8; len as usize];
181    let n = fill(&mut tmp)?;
182    write_bytes(mem, ptr, len, &tmp[..n])
183}
184
185// --- enum conversions -------------------------------------------------------
186
187impl From<types::AlgorithmType> for HostAlgorithmType {
188    fn from(a: types::AlgorithmType) -> Self {
189        match a {
190            types::AlgorithmType::Signatures => HostAlgorithmType::Signatures,
191            types::AlgorithmType::Symmetric => HostAlgorithmType::Symmetric,
192            types::AlgorithmType::KeyExchange => HostAlgorithmType::KeyExchange,
193        }
194    }
195}
196
197impl From<types::KeypairEncoding> for KeyPairEncoding {
198    fn from(e: types::KeypairEncoding) -> Self {
199        match e {
200            types::KeypairEncoding::Raw => KeyPairEncoding::Raw,
201            types::KeypairEncoding::Pkcs8 => KeyPairEncoding::Pkcs8,
202            types::KeypairEncoding::Pem => KeyPairEncoding::Pem,
203            types::KeypairEncoding::Local => KeyPairEncoding::Local,
204        }
205    }
206}
207
208impl From<types::PublickeyEncoding> for PublicKeyEncoding {
209    fn from(e: types::PublickeyEncoding) -> Self {
210        match e {
211            types::PublickeyEncoding::Raw => PublicKeyEncoding::Raw,
212            types::PublickeyEncoding::Pkcs8 => PublicKeyEncoding::Pkcs8,
213            types::PublickeyEncoding::Pem => PublicKeyEncoding::Pem,
214            types::PublickeyEncoding::Sec => PublicKeyEncoding::Sec,
215            types::PublickeyEncoding::Local => PublicKeyEncoding::Local,
216        }
217    }
218}
219
220impl From<types::SecretkeyEncoding> for SecretKeyEncoding {
221    fn from(e: types::SecretkeyEncoding) -> Self {
222        match e {
223            types::SecretkeyEncoding::Raw => SecretKeyEncoding::Raw,
224            types::SecretkeyEncoding::Pkcs8 => SecretKeyEncoding::Pkcs8,
225            types::SecretkeyEncoding::Pem => SecretKeyEncoding::Pem,
226            types::SecretkeyEncoding::Sec => SecretKeyEncoding::Sec,
227            types::SecretkeyEncoding::Local => SecretKeyEncoding::Local,
228        }
229    }
230}
231
232impl From<types::SignatureEncoding> for SignatureEncoding {
233    fn from(e: types::SignatureEncoding) -> Self {
234        match e {
235            types::SignatureEncoding::Raw => SignatureEncoding::Raw,
236            types::SignatureEncoding::Der => SignatureEncoding::Der,
237        }
238    }
239}
240
241fn opt_options(o: &types::OptOptions) -> Option<Handle> {
242    match o {
243        types::OptOptions::Some(h) => Some((*h).into()),
244        types::OptOptions::None => None,
245    }
246}
247
248fn opt_symmetric_key(o: &types::OptSymmetricKey) -> Option<Handle> {
249    match o {
250        types::OptSymmetricKey::Some(h) => Some((*h).into()),
251        types::OptSymmetricKey::None => None,
252    }
253}
254
255// --- common -----------------------------------------------------------------
256
257impl generated::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryptoCtx {
258    fn options_open(
259        &mut self,
260        _mem: &mut GuestMemory<'_>,
261        algorithm_type: types::AlgorithmType,
262    ) -> WResult<types::Options> {
263        Ok(self.ctx.options_open(algorithm_type.into())?.into())
264    }
265
266    fn options_close(&mut self, _mem: &mut GuestMemory<'_>, handle: types::Options) -> WResult<()> {
267        Ok(self.ctx.options_close(handle.into())?)
268    }
269
270    fn options_set(
271        &mut self,
272        mem: &mut GuestMemory<'_>,
273        handle: types::Options,
274        name: GuestPtr<str>,
275        value: GuestPtr<u8>,
276        value_len: types::Size,
277    ) -> WResult<()> {
278        let name = read_str(mem, name)?;
279        let value = read_bytes(mem, value, value_len)?;
280        Ok(self.ctx.options_set(handle.into(), &name, &value)?)
281    }
282
283    fn options_set_u64(
284        &mut self,
285        mem: &mut GuestMemory<'_>,
286        handle: types::Options,
287        name: GuestPtr<str>,
288        value: u64,
289    ) -> WResult<()> {
290        let name = read_str(mem, name)?;
291        Ok(self.ctx.options_set_u64(handle.into(), &name, value)?)
292    }
293
294    fn options_set_guest_buffer(
295        &mut self,
296        mem: &mut GuestMemory<'_>,
297        _handle: types::Options,
298        name: GuestPtr<str>,
299        _buffer: GuestPtr<u8>,
300        _buffer_len: types::Size,
301    ) -> WResult<()> {
302        // The guest-buffer fast-path lets memory-hard functions scribble their
303        // scratch space straight into guest memory. It needs a `'static mut`
304        // view of guest memory, which can't be produced soundly under Wiggle's
305        // borrow model (the memory may grow and move). None of the algorithms
306        // implemented by the host actually read this buffer back, so accepting
307        // the option without storing it is behaviourally equivalent here.
308        let _ = read_str(mem, name)?;
309        Ok(())
310    }
311
312    fn array_output_len(
313        &mut self,
314        _mem: &mut GuestMemory<'_>,
315        array_output: types::ArrayOutput,
316    ) -> WResult<types::Size> {
317        Ok(self.ctx.array_output_len(array_output.into())? as types::Size)
318    }
319
320    fn array_output_pull(
321        &mut self,
322        mem: &mut GuestMemory<'_>,
323        array_output: types::ArrayOutput,
324        buf: GuestPtr<u8>,
325        buf_len: types::Size,
326    ) -> WResult<types::Size> {
327        fill_out_buf(mem, buf, buf_len, |out| {
328            self.ctx.array_output_pull(array_output.into(), out)
329        })
330    }
331
332    fn secrets_manager_open(
333        &mut self,
334        _mem: &mut GuestMemory<'_>,
335        options: &types::OptOptions,
336    ) -> WResult<types::SecretsManager> {
337        Ok(self.ctx.secrets_manager_open(opt_options(options))?.into())
338    }
339
340    fn secrets_manager_close(
341        &mut self,
342        _mem: &mut GuestMemory<'_>,
343        secrets_manager: types::SecretsManager,
344    ) -> WResult<()> {
345        Ok(self.ctx.secrets_manager_close(secrets_manager.into())?)
346    }
347
348    fn secrets_manager_invalidate(
349        &mut self,
350        mem: &mut GuestMemory<'_>,
351        secrets_manager: types::SecretsManager,
352        key_id: GuestPtr<u8>,
353        key_id_len: types::Size,
354        key_version: types::Version,
355    ) -> WResult<()> {
356        let key_id = read_bytes(mem, key_id, key_id_len)?;
357        Ok(self.ctx.secrets_manager_invalidate(
358            secrets_manager.into(),
359            &key_id,
360            Version(key_version),
361        )?)
362    }
363}
364
365// --- asymmetric_common ------------------------------------------------------
366
367impl generated::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetricCommon
368    for WasiCryptoCtx
369{
370    fn keypair_generate(
371        &mut self,
372        mem: &mut GuestMemory<'_>,
373        algorithm_type: types::AlgorithmType,
374        algorithm: GuestPtr<str>,
375        options: &types::OptOptions,
376    ) -> WResult<types::Keypair> {
377        let alg = read_str(mem, algorithm)?;
378        Ok(self
379            .ctx
380            .keypair_generate(algorithm_type.into(), &alg, opt_options(options))?
381            .into())
382    }
383
384    fn keypair_import(
385        &mut self,
386        mem: &mut GuestMemory<'_>,
387        algorithm_type: types::AlgorithmType,
388        algorithm: GuestPtr<str>,
389        encoded: GuestPtr<u8>,
390        encoded_len: types::Size,
391        encoding: types::KeypairEncoding,
392    ) -> WResult<types::Keypair> {
393        let alg = read_str(mem, algorithm)?;
394        let encoded = read_bytes(mem, encoded, encoded_len)?;
395        Ok(self
396            .ctx
397            .keypair_import(algorithm_type.into(), &alg, &encoded, encoding.into())?
398            .into())
399    }
400
401    fn keypair_generate_managed(
402        &mut self,
403        mem: &mut GuestMemory<'_>,
404        secrets_manager: types::SecretsManager,
405        algorithm_type: types::AlgorithmType,
406        algorithm: GuestPtr<str>,
407        options: &types::OptOptions,
408    ) -> WResult<types::Keypair> {
409        let alg = read_str(mem, algorithm)?;
410        Ok(self
411            .ctx
412            .keypair_generate_managed(
413                secrets_manager.into(),
414                algorithm_type.into(),
415                &alg,
416                opt_options(options),
417            )?
418            .into())
419    }
420
421    fn keypair_store_managed(
422        &mut self,
423        mem: &mut GuestMemory<'_>,
424        secrets_manager: types::SecretsManager,
425        kp: types::Keypair,
426        kp_id: GuestPtr<u8>,
427        kp_id_max_len: types::Size,
428    ) -> WResult<()> {
429        let mut tmp = vec![0u8; kp_id_max_len as usize];
430        self.ctx
431            .keypair_store_managed(secrets_manager.into(), kp.into(), &mut tmp)?;
432        write_bytes(mem, kp_id, kp_id_max_len, &tmp)?;
433        Ok(())
434    }
435
436    fn keypair_replace_managed(
437        &mut self,
438        _mem: &mut GuestMemory<'_>,
439        secrets_manager: types::SecretsManager,
440        kp_old: types::Keypair,
441        kp_new: types::Keypair,
442    ) -> WResult<types::Version> {
443        Ok(self
444            .ctx
445            .keypair_replace_managed(secrets_manager.into(), kp_old.into(), kp_new.into())?
446            .0)
447    }
448
449    fn keypair_id(
450        &mut self,
451        mem: &mut GuestMemory<'_>,
452        kp: types::Keypair,
453        kp_id: GuestPtr<u8>,
454        kp_id_max_len: types::Size,
455    ) -> WResult<(types::Size, types::Version)> {
456        let (id, version) = self.ctx.keypair_id(kp.into())?;
457        let n = write_bytes(mem, kp_id, kp_id_max_len, &id)?;
458        Ok((n, version.0))
459    }
460
461    fn keypair_from_id(
462        &mut self,
463        mem: &mut GuestMemory<'_>,
464        secrets_manager: types::SecretsManager,
465        kp_id: GuestPtr<u8>,
466        kp_id_len: types::Size,
467        kp_version: types::Version,
468    ) -> WResult<types::Keypair> {
469        let kp_id = read_bytes(mem, kp_id, kp_id_len)?;
470        Ok(self
471            .ctx
472            .keypair_from_id(secrets_manager.into(), &kp_id, Version(kp_version))?
473            .into())
474    }
475
476    fn keypair_from_pk_and_sk(
477        &mut self,
478        _mem: &mut GuestMemory<'_>,
479        publickey: types::Publickey,
480        secretkey: types::Secretkey,
481    ) -> WResult<types::Keypair> {
482        Ok(self
483            .ctx
484            .keypair_from_pk_and_sk(publickey.into(), secretkey.into())?
485            .into())
486    }
487
488    fn keypair_export(
489        &mut self,
490        _mem: &mut GuestMemory<'_>,
491        kp: types::Keypair,
492        encoding: types::KeypairEncoding,
493    ) -> WResult<types::ArrayOutput> {
494        Ok(self.ctx.keypair_export(kp.into(), encoding.into())?.into())
495    }
496
497    fn keypair_publickey(
498        &mut self,
499        _mem: &mut GuestMemory<'_>,
500        kp: types::Keypair,
501    ) -> WResult<types::Publickey> {
502        Ok(self.ctx.keypair_publickey(kp.into())?.into())
503    }
504
505    fn keypair_secretkey(
506        &mut self,
507        _mem: &mut GuestMemory<'_>,
508        kp: types::Keypair,
509    ) -> WResult<types::Secretkey> {
510        Ok(self.ctx.keypair_secretkey(kp.into())?.into())
511    }
512
513    fn keypair_close(&mut self, _mem: &mut GuestMemory<'_>, kp: types::Keypair) -> WResult<()> {
514        Ok(self.ctx.keypair_close(kp.into())?)
515    }
516
517    fn publickey_import(
518        &mut self,
519        mem: &mut GuestMemory<'_>,
520        algorithm_type: types::AlgorithmType,
521        algorithm: GuestPtr<str>,
522        encoded: GuestPtr<u8>,
523        encoded_len: types::Size,
524        encoding: types::PublickeyEncoding,
525    ) -> WResult<types::Publickey> {
526        let alg = read_str(mem, algorithm)?;
527        let encoded = read_bytes(mem, encoded, encoded_len)?;
528        Ok(self
529            .ctx
530            .publickey_import(algorithm_type.into(), &alg, &encoded, encoding.into())?
531            .into())
532    }
533
534    fn publickey_export(
535        &mut self,
536        _mem: &mut GuestMemory<'_>,
537        pk: types::Publickey,
538        encoding: types::PublickeyEncoding,
539    ) -> WResult<types::ArrayOutput> {
540        Ok(self
541            .ctx
542            .publickey_export(pk.into(), encoding.into())?
543            .into())
544    }
545
546    fn publickey_verify(
547        &mut self,
548        _mem: &mut GuestMemory<'_>,
549        pk: types::Publickey,
550    ) -> WResult<()> {
551        Ok(self.ctx.publickey_verify(pk.into())?)
552    }
553
554    fn publickey_from_secretkey(
555        &mut self,
556        _mem: &mut GuestMemory<'_>,
557        sk: types::Secretkey,
558    ) -> WResult<types::Publickey> {
559        Ok(self.ctx.publickey(sk.into())?.into())
560    }
561
562    fn publickey_close(&mut self, _mem: &mut GuestMemory<'_>, pk: types::Publickey) -> WResult<()> {
563        Ok(self.ctx.publickey_close(pk.into())?)
564    }
565
566    fn secretkey_import(
567        &mut self,
568        mem: &mut GuestMemory<'_>,
569        algorithm_type: types::AlgorithmType,
570        algorithm: GuestPtr<str>,
571        encoded: GuestPtr<u8>,
572        encoded_len: types::Size,
573        encoding: types::SecretkeyEncoding,
574    ) -> WResult<types::Secretkey> {
575        let alg = read_str(mem, algorithm)?;
576        let encoded = read_bytes(mem, encoded, encoded_len)?;
577        Ok(self
578            .ctx
579            .secretkey_import(algorithm_type.into(), &alg, &encoded, encoding.into())?
580            .into())
581    }
582
583    fn secretkey_export(
584        &mut self,
585        _mem: &mut GuestMemory<'_>,
586        sk: types::Secretkey,
587        encoding: types::SecretkeyEncoding,
588    ) -> WResult<types::ArrayOutput> {
589        Ok(self
590            .ctx
591            .secretkey_export(sk.into(), encoding.into())?
592            .into())
593    }
594
595    fn secretkey_close(&mut self, _mem: &mut GuestMemory<'_>, sk: types::Secretkey) -> WResult<()> {
596        Ok(self.ctx.secretkey_close(sk.into())?)
597    }
598}
599
600// --- signatures -------------------------------------------------------------
601
602impl generated::wasi_ephemeral_crypto_signatures::WasiEphemeralCryptoSignatures for WasiCryptoCtx {
603    fn signature_export(
604        &mut self,
605        _mem: &mut GuestMemory<'_>,
606        signature: types::Signature,
607        encoding: types::SignatureEncoding,
608    ) -> WResult<types::ArrayOutput> {
609        Ok(self
610            .ctx
611            .signature_export(signature.into(), encoding.into())?
612            .into())
613    }
614
615    fn signature_import(
616        &mut self,
617        mem: &mut GuestMemory<'_>,
618        algorithm: GuestPtr<str>,
619        encoded: GuestPtr<u8>,
620        encoded_len: types::Size,
621        encoding: types::SignatureEncoding,
622    ) -> WResult<types::Signature> {
623        let alg = read_str(mem, algorithm)?;
624        let encoded = read_bytes(mem, encoded, encoded_len)?;
625        Ok(self
626            .ctx
627            .signature_import(&alg, &encoded, encoding.into())?
628            .into())
629    }
630
631    fn signature_state_open(
632        &mut self,
633        _mem: &mut GuestMemory<'_>,
634        kp: types::SignatureKeypair,
635    ) -> WResult<types::SignatureState> {
636        Ok(self.ctx.signature_state_open(kp.into())?.into())
637    }
638
639    fn signature_state_update(
640        &mut self,
641        mem: &mut GuestMemory<'_>,
642        state: types::SignatureState,
643        input: GuestPtr<u8>,
644        input_len: types::Size,
645    ) -> WResult<()> {
646        let input = read_bytes(mem, input, input_len)?;
647        Ok(self.ctx.signature_state_update(state.into(), &input)?)
648    }
649
650    fn signature_state_sign(
651        &mut self,
652        _mem: &mut GuestMemory<'_>,
653        state: types::SignatureState,
654    ) -> WResult<types::ArrayOutput> {
655        Ok(self.ctx.signature_state_sign(state.into())?.into())
656    }
657
658    fn signature_state_close(
659        &mut self,
660        _mem: &mut GuestMemory<'_>,
661        state: types::SignatureState,
662    ) -> WResult<()> {
663        Ok(self.ctx.signature_state_close(state.into())?)
664    }
665
666    fn signature_verification_state_open(
667        &mut self,
668        _mem: &mut GuestMemory<'_>,
669        kp: types::SignaturePublickey,
670    ) -> WResult<types::SignatureVerificationState> {
671        Ok(self
672            .ctx
673            .signature_verification_state_open(kp.into())?
674            .into())
675    }
676
677    fn signature_verification_state_update(
678        &mut self,
679        mem: &mut GuestMemory<'_>,
680        state: types::SignatureVerificationState,
681        input: GuestPtr<u8>,
682        input_len: types::Size,
683    ) -> WResult<()> {
684        let input = read_bytes(mem, input, input_len)?;
685        Ok(self
686            .ctx
687            .signature_verification_state_update(state.into(), &input)?)
688    }
689
690    fn signature_verification_state_verify(
691        &mut self,
692        _mem: &mut GuestMemory<'_>,
693        state: types::SignatureVerificationState,
694        signature: types::Signature,
695    ) -> WResult<()> {
696        Ok(self
697            .ctx
698            .signature_verification_state_verify(state.into(), signature.into())?)
699    }
700
701    fn signature_verification_state_close(
702        &mut self,
703        _mem: &mut GuestMemory<'_>,
704        state: types::SignatureVerificationState,
705    ) -> WResult<()> {
706        Ok(self.ctx.signature_verification_state_close(state.into())?)
707    }
708
709    fn signature_close(
710        &mut self,
711        _mem: &mut GuestMemory<'_>,
712        signature: types::Signature,
713    ) -> WResult<()> {
714        Ok(self.ctx.signature_close(signature.into())?)
715    }
716}
717
718// --- key exchange -----------------------------------------------------------
719
720impl generated::wasi_ephemeral_crypto_kx::WasiEphemeralCryptoKx for WasiCryptoCtx {
721    fn kx_dh(
722        &mut self,
723        _mem: &mut GuestMemory<'_>,
724        pk: types::Publickey,
725        sk: types::Secretkey,
726    ) -> WResult<types::ArrayOutput> {
727        Ok(self.ctx.kx_dh(pk.into(), sk.into())?.into())
728    }
729
730    fn kx_encapsulate(
731        &mut self,
732        _mem: &mut GuestMemory<'_>,
733        pk: types::Publickey,
734    ) -> WResult<(types::ArrayOutput, types::ArrayOutput)> {
735        let (secret, encapsulated) = self.ctx.kx_encapsulate(pk.into())?;
736        Ok((secret.into(), encapsulated.into()))
737    }
738
739    fn kx_decapsulate(
740        &mut self,
741        mem: &mut GuestMemory<'_>,
742        sk: types::Secretkey,
743        encapsulated_secret: GuestPtr<u8>,
744        encapsulated_secret_len: types::Size,
745    ) -> WResult<types::ArrayOutput> {
746        let encapsulated = read_bytes(mem, encapsulated_secret, encapsulated_secret_len)?;
747        Ok(self.ctx.kx_decapsulate(sk.into(), &encapsulated)?.into())
748    }
749}
750
751// --- symmetric --------------------------------------------------------------
752
753impl generated::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for WasiCryptoCtx {
754    fn symmetric_key_generate(
755        &mut self,
756        mem: &mut GuestMemory<'_>,
757        algorithm: GuestPtr<str>,
758        options: &types::OptOptions,
759    ) -> WResult<types::SymmetricKey> {
760        let alg = read_str(mem, algorithm)?;
761        Ok(self
762            .ctx
763            .symmetric_key_generate(&alg, opt_options(options))?
764            .into())
765    }
766
767    fn symmetric_key_import(
768        &mut self,
769        mem: &mut GuestMemory<'_>,
770        algorithm: GuestPtr<str>,
771        raw: GuestPtr<u8>,
772        raw_len: types::Size,
773    ) -> WResult<types::SymmetricKey> {
774        let alg = read_str(mem, algorithm)?;
775        let raw = read_bytes(mem, raw, raw_len)?;
776        Ok(self.ctx.symmetric_key_import(&alg, &raw)?.into())
777    }
778
779    fn symmetric_key_export(
780        &mut self,
781        _mem: &mut GuestMemory<'_>,
782        symmetric_key: types::SymmetricKey,
783    ) -> WResult<types::ArrayOutput> {
784        Ok(self.ctx.symmetric_key_export(symmetric_key.into())?.into())
785    }
786
787    fn symmetric_key_close(
788        &mut self,
789        _mem: &mut GuestMemory<'_>,
790        symmetric_key: types::SymmetricKey,
791    ) -> WResult<()> {
792        Ok(self.ctx.symmetric_key_close(symmetric_key.into())?)
793    }
794
795    fn symmetric_key_generate_managed(
796        &mut self,
797        mem: &mut GuestMemory<'_>,
798        secrets_manager: types::SecretsManager,
799        algorithm: GuestPtr<str>,
800        options: &types::OptOptions,
801    ) -> WResult<types::SymmetricKey> {
802        let alg = read_str(mem, algorithm)?;
803        Ok(self
804            .ctx
805            .symmetric_key_generate_managed(secrets_manager.into(), &alg, opt_options(options))?
806            .into())
807    }
808
809    fn symmetric_key_store_managed(
810        &mut self,
811        mem: &mut GuestMemory<'_>,
812        secrets_manager: types::SecretsManager,
813        symmetric_key: types::SymmetricKey,
814        symmetric_key_id: GuestPtr<u8>,
815        symmetric_key_id_max_len: types::Size,
816    ) -> WResult<()> {
817        let mut tmp = vec![0u8; symmetric_key_id_max_len as usize];
818        self.ctx.symmetric_key_store_managed(
819            secrets_manager.into(),
820            symmetric_key.into(),
821            &mut tmp,
822        )?;
823        write_bytes(mem, symmetric_key_id, symmetric_key_id_max_len, &tmp)?;
824        Ok(())
825    }
826
827    fn symmetric_key_replace_managed(
828        &mut self,
829        _mem: &mut GuestMemory<'_>,
830        secrets_manager: types::SecretsManager,
831        symmetric_key_old: types::SymmetricKey,
832        symmetric_key_new: types::SymmetricKey,
833    ) -> WResult<types::Version> {
834        Ok(self
835            .ctx
836            .symmetric_key_replace_managed(
837                secrets_manager.into(),
838                symmetric_key_old.into(),
839                symmetric_key_new.into(),
840            )?
841            .0)
842    }
843
844    fn symmetric_key_id(
845        &mut self,
846        mem: &mut GuestMemory<'_>,
847        symmetric_key: types::SymmetricKey,
848        symmetric_key_id: GuestPtr<u8>,
849        symmetric_key_id_max_len: types::Size,
850    ) -> WResult<(types::Size, types::Version)> {
851        let (id, version) = self.ctx.symmetric_key_id(symmetric_key.into())?;
852        let n = write_bytes(mem, symmetric_key_id, symmetric_key_id_max_len, &id)?;
853        Ok((n, version.0))
854    }
855
856    fn symmetric_key_from_id(
857        &mut self,
858        mem: &mut GuestMemory<'_>,
859        secrets_manager: types::SecretsManager,
860        symmetric_key_id: GuestPtr<u8>,
861        symmetric_key_id_len: types::Size,
862        symmetric_key_version: types::Version,
863    ) -> WResult<types::SymmetricKey> {
864        let id = read_bytes(mem, symmetric_key_id, symmetric_key_id_len)?;
865        Ok(self
866            .ctx
867            .symmetric_key_from_id(secrets_manager.into(), &id, Version(symmetric_key_version))?
868            .into())
869    }
870
871    fn symmetric_state_open(
872        &mut self,
873        mem: &mut GuestMemory<'_>,
874        algorithm: GuestPtr<str>,
875        key: &types::OptSymmetricKey,
876        options: &types::OptOptions,
877    ) -> WResult<types::SymmetricState> {
878        let alg = read_str(mem, algorithm)?;
879        Ok(self
880            .ctx
881            .symmetric_state_open(&alg, opt_symmetric_key(key), opt_options(options))?
882            .into())
883    }
884
885    fn symmetric_state_options_get(
886        &mut self,
887        mem: &mut GuestMemory<'_>,
888        handle: types::SymmetricState,
889        name: GuestPtr<str>,
890        value: GuestPtr<u8>,
891        value_max_len: types::Size,
892    ) -> WResult<types::Size> {
893        let name = read_str(mem, name)?;
894        fill_out_buf(mem, value, value_max_len, |out| {
895            self.ctx
896                .symmetric_state_options_get(handle.into(), &name, out)
897        })
898    }
899
900    fn symmetric_state_options_get_u64(
901        &mut self,
902        mem: &mut GuestMemory<'_>,
903        handle: types::SymmetricState,
904        name: GuestPtr<str>,
905    ) -> WResult<u64> {
906        let name = read_str(mem, name)?;
907        Ok(self
908            .ctx
909            .symmetric_state_options_get_u64(handle.into(), &name)?)
910    }
911
912    fn symmetric_state_clone(
913        &mut self,
914        _mem: &mut GuestMemory<'_>,
915        handle: types::SymmetricState,
916    ) -> WResult<types::SymmetricState> {
917        Ok(self.ctx.symmetric_state_clone(handle.into())?.into())
918    }
919
920    fn symmetric_state_close(
921        &mut self,
922        _mem: &mut GuestMemory<'_>,
923        handle: types::SymmetricState,
924    ) -> WResult<()> {
925        Ok(self.ctx.symmetric_state_close(handle.into())?)
926    }
927
928    fn symmetric_state_absorb(
929        &mut self,
930        mem: &mut GuestMemory<'_>,
931        handle: types::SymmetricState,
932        data: GuestPtr<u8>,
933        data_len: types::Size,
934    ) -> WResult<()> {
935        let data = read_bytes(mem, data, data_len)?;
936        Ok(self.ctx.symmetric_state_absorb(handle.into(), &data)?)
937    }
938
939    fn symmetric_state_squeeze(
940        &mut self,
941        mem: &mut GuestMemory<'_>,
942        handle: types::SymmetricState,
943        out: GuestPtr<u8>,
944        out_len: types::Size,
945    ) -> WResult<()> {
946        let mut tmp = vec![0u8; out_len as usize];
947        self.ctx.symmetric_state_squeeze(handle.into(), &mut tmp)?;
948        write_bytes(mem, out, out_len, &tmp)?;
949        Ok(())
950    }
951
952    fn symmetric_state_squeeze_tag(
953        &mut self,
954        _mem: &mut GuestMemory<'_>,
955        handle: types::SymmetricState,
956    ) -> WResult<types::SymmetricTag> {
957        Ok(self.ctx.symmetric_state_squeeze_tag(handle.into())?.into())
958    }
959
960    fn symmetric_state_squeeze_key(
961        &mut self,
962        mem: &mut GuestMemory<'_>,
963        handle: types::SymmetricState,
964        alg_str: GuestPtr<str>,
965    ) -> WResult<types::SymmetricKey> {
966        let alg = read_str(mem, alg_str)?;
967        Ok(self
968            .ctx
969            .symmetric_state_squeeze_key(handle.into(), &alg)?
970            .into())
971    }
972
973    fn symmetric_state_max_tag_len(
974        &mut self,
975        _mem: &mut GuestMemory<'_>,
976        handle: types::SymmetricState,
977    ) -> WResult<types::Size> {
978        Ok(self.ctx.symmetric_state_max_tag_len(handle.into())? as types::Size)
979    }
980
981    fn symmetric_state_encrypt(
982        &mut self,
983        mem: &mut GuestMemory<'_>,
984        handle: types::SymmetricState,
985        out: GuestPtr<u8>,
986        out_len: types::Size,
987        data: GuestPtr<u8>,
988        data_len: types::Size,
989    ) -> WResult<types::Size> {
990        let data = read_bytes(mem, data, data_len)?;
991        fill_out_buf(mem, out, out_len, |buf| {
992            self.ctx.symmetric_state_encrypt(handle.into(), buf, &data)
993        })
994    }
995
996    fn symmetric_state_encrypt_detached(
997        &mut self,
998        mem: &mut GuestMemory<'_>,
999        handle: types::SymmetricState,
1000        out: GuestPtr<u8>,
1001        out_len: types::Size,
1002        data: GuestPtr<u8>,
1003        data_len: types::Size,
1004    ) -> WResult<types::SymmetricTag> {
1005        let data = read_bytes(mem, data, data_len)?;
1006        let mut tmp = vec![0u8; out_len as usize];
1007        let tag = self
1008            .ctx
1009            .symmetric_state_encrypt_detached(handle.into(), &mut tmp, &data)?;
1010        write_bytes(mem, out, out_len, &tmp)?;
1011        Ok(tag.into())
1012    }
1013
1014    fn symmetric_state_decrypt(
1015        &mut self,
1016        mem: &mut GuestMemory<'_>,
1017        handle: types::SymmetricState,
1018        out: GuestPtr<u8>,
1019        out_len: types::Size,
1020        data: GuestPtr<u8>,
1021        data_len: types::Size,
1022    ) -> WResult<types::Size> {
1023        let data = read_bytes(mem, data, data_len)?;
1024        fill_out_buf(mem, out, out_len, |buf| {
1025            self.ctx.symmetric_state_decrypt(handle.into(), buf, &data)
1026        })
1027    }
1028
1029    fn symmetric_state_decrypt_detached(
1030        &mut self,
1031        mem: &mut GuestMemory<'_>,
1032        handle: types::SymmetricState,
1033        out: GuestPtr<u8>,
1034        out_len: types::Size,
1035        data: GuestPtr<u8>,
1036        data_len: types::Size,
1037        raw_tag: GuestPtr<u8>,
1038        raw_tag_len: types::Size,
1039    ) -> WResult<types::Size> {
1040        let data = read_bytes(mem, data, data_len)?;
1041        let raw_tag = read_bytes(mem, raw_tag, raw_tag_len)?;
1042        fill_out_buf(mem, out, out_len, |buf| {
1043            self.ctx
1044                .symmetric_state_decrypt_detached(handle.into(), buf, &data, &raw_tag)
1045        })
1046    }
1047
1048    fn symmetric_state_ratchet(
1049        &mut self,
1050        _mem: &mut GuestMemory<'_>,
1051        handle: types::SymmetricState,
1052    ) -> WResult<()> {
1053        Ok(self.ctx.symmetric_state_ratchet(handle.into())?)
1054    }
1055
1056    fn symmetric_tag_len(
1057        &mut self,
1058        _mem: &mut GuestMemory<'_>,
1059        symmetric_tag: types::SymmetricTag,
1060    ) -> WResult<types::Size> {
1061        Ok(self.ctx.symmetric_tag_len(symmetric_tag.into())? as types::Size)
1062    }
1063
1064    fn symmetric_tag_pull(
1065        &mut self,
1066        mem: &mut GuestMemory<'_>,
1067        symmetric_tag: types::SymmetricTag,
1068        buf: GuestPtr<u8>,
1069        buf_len: types::Size,
1070    ) -> WResult<types::Size> {
1071        fill_out_buf(mem, buf, buf_len, |out| {
1072            self.ctx.symmetric_tag_pull(symmetric_tag.into(), out)
1073        })
1074    }
1075
1076    fn symmetric_tag_verify(
1077        &mut self,
1078        mem: &mut GuestMemory<'_>,
1079        symmetric_tag: types::SymmetricTag,
1080        expected_raw_tag_ptr: GuestPtr<u8>,
1081        expected_raw_tag_len: types::Size,
1082    ) -> WResult<()> {
1083        let expected = read_bytes(mem, expected_raw_tag_ptr, expected_raw_tag_len)?;
1084        Ok(self
1085            .ctx
1086            .symmetric_tag_verify(symmetric_tag.into(), &expected)?)
1087    }
1088
1089    fn symmetric_tag_close(
1090        &mut self,
1091        _mem: &mut GuestMemory<'_>,
1092        symmetric_tag: types::SymmetricTag,
1093    ) -> WResult<()> {
1094        Ok(self.ctx.symmetric_tag_close(symmetric_tag.into())?)
1095    }
1096}