wasmtime_vfs_keyfs/
generate.rs

1use std::any::Any;
2use std::io::{IoSlice, IoSliceMut};
3use std::sync::Arc;
4
5use digest::generic_array::ArrayLength;
6use digest::Digest;
7use ecdsa::elliptic_curve::ops::{Invert, Reduce};
8use ecdsa::elliptic_curve::subtle::CtOption;
9use ecdsa::elliptic_curve::{ProjectiveArithmetic, Scalar};
10use ecdsa::hazmat::SignPrimitive;
11use ecdsa::{PrimeCurve, SignatureSize};
12use rsa::PublicKeyParts;
13use sha2::{Sha256, Sha384, Sha512};
14use signature::{DigestVerifier, RandomizedDigestSigner, Signature};
15use uuid::Uuid;
16use wasi_common::file::{FdFlags, FileType, Filestat, RiFlags, RoFlags, SiFlags};
17use wasi_common::{Error, ErrorExt, ErrorKind, WasiDir, WasiFile};
18use wasmtime_vfs_dir::Directory;
19use wasmtime_vfs_ledger::InodeId;
20use wasmtime_vfs_memory::{Data, Inode, Link, Node};
21
22use crate::share::Share;
23use crate::sign::Sign;
24use crate::verify::Verify;
25use crate::{ES256, ES256K, ES384, PS256, PS384, PS512, RS256, RS384, RS512};
26
27type Rs256 = rsa::pkcs1v15::SigningKey<Sha256>;
28type Rs384 = rsa::pkcs1v15::SigningKey<Sha384>;
29type Rs512 = rsa::pkcs1v15::SigningKey<Sha512>;
30type Ps256 = rsa::pss::BlindedSigningKey<Sha256>;
31type Ps384 = rsa::pss::BlindedSigningKey<Sha384>;
32type Ps512 = rsa::pss::BlindedSigningKey<Sha512>;
33type Es256k = ecdsa::SigningKey<k256::Secp256k1>;
34type Es256 = ecdsa::SigningKey<p256::NistP256>;
35type Es384 = ecdsa::SigningKey<p384::NistP384>;
36
37trait GenerateKey: Sized {
38    fn generate() -> Result<Self, Error>;
39}
40
41impl GenerateKey for Rs256 {
42    fn generate() -> Result<Self, Error> {
43        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 2048)?.into())
44    }
45}
46
47impl GenerateKey for Rs384 {
48    fn generate() -> Result<Self, Error> {
49        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 3072)?.into())
50    }
51}
52
53impl GenerateKey for Rs512 {
54    fn generate() -> Result<Self, Error> {
55        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 4096)?.into())
56    }
57}
58
59impl GenerateKey for Ps256 {
60    fn generate() -> Result<Self, Error> {
61        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 2048)?.into())
62    }
63}
64
65impl GenerateKey for Ps384 {
66    fn generate() -> Result<Self, Error> {
67        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 3072)?.into())
68    }
69}
70
71impl GenerateKey for Ps512 {
72    fn generate() -> Result<Self, Error> {
73        Ok(rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 4096)?.into())
74    }
75}
76
77impl GenerateKey for Es256k {
78    fn generate() -> Result<Self, Error> {
79        Ok(ecdsa::SigningKey::random(&mut rand::thread_rng()))
80    }
81}
82
83impl GenerateKey for Es256 {
84    fn generate() -> Result<Self, Error> {
85        Ok(ecdsa::SigningKey::random(&mut rand::thread_rng()))
86    }
87}
88
89impl GenerateKey for Es384 {
90    fn generate() -> Result<Self, Error> {
91        Ok(ecdsa::SigningKey::random(&mut rand::thread_rng()))
92    }
93}
94
95trait ToPublic {
96    type Public;
97
98    fn to_public(&self) -> Self::Public;
99}
100
101impl<D: Digest> ToPublic for rsa::pkcs1v15::SigningKey<D> {
102    type Public = rsa::pkcs1v15::VerifyingKey<D>;
103
104    fn to_public(&self) -> Self::Public {
105        Self::Public::from(self)
106    }
107}
108
109impl<D: Digest> ToPublic for rsa::pss::BlindedSigningKey<D> {
110    type Public = rsa::pss::VerifyingKey<D>;
111
112    fn to_public(&self) -> Self::Public {
113        Self::Public::from(self)
114    }
115}
116
117impl<C: ecdsa::elliptic_curve::Curve> ToPublic for ecdsa::SigningKey<C>
118where
119    C: PrimeCurve + ProjectiveArithmetic,
120    Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + Reduce<C::UInt> + SignPrimitive<C>,
121    SignatureSize<C>: ArrayLength<u8>,
122{
123    type Public = ecdsa::VerifyingKey<C>;
124
125    fn to_public(&self) -> Self::Public {
126        Self::Public::from(self)
127    }
128}
129
130trait Encoder<T> {
131    fn encode(&self, arg: T) -> Result<Vec<u8>, Error>;
132}
133
134impl Encoder<&[u8]> for rsa::RsaPublicKey {
135    fn encode(&self, prefix: &[u8]) -> Result<Vec<u8>, Error> {
136        let e = self.e().to_bytes_be();
137        let n = self.n().to_bytes_be();
138
139        let el = u32::try_from(e.len()).map_err(|_| Error::io())?;
140        let nl = u32::try_from(n.len()).map_err(|_| Error::io())?;
141
142        let mut out = prefix.to_vec();
143        out.extend_from_slice(&el.to_be_bytes());
144        out.extend_from_slice(&e);
145        out.extend_from_slice(&nl.to_be_bytes());
146        out.extend_from_slice(&n);
147
148        Ok(out)
149    }
150}
151
152impl Encoder<()> for rsa::pkcs1v15::VerifyingKey<Sha256> {
153    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
154        self.as_ref().encode(RS256)
155    }
156}
157
158impl Encoder<()> for rsa::pkcs1v15::VerifyingKey<Sha384> {
159    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
160        self.as_ref().encode(RS384)
161    }
162}
163
164impl Encoder<()> for rsa::pkcs1v15::VerifyingKey<Sha512> {
165    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
166        self.as_ref().encode(RS512)
167    }
168}
169
170impl Encoder<()> for rsa::pss::VerifyingKey<Sha256> {
171    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
172        self.as_ref().encode(PS256)
173    }
174}
175
176impl Encoder<()> for rsa::pss::VerifyingKey<Sha384> {
177    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
178        self.as_ref().encode(PS384)
179    }
180}
181
182impl Encoder<()> for rsa::pss::VerifyingKey<Sha512> {
183    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
184        self.as_ref().encode(PS512)
185    }
186}
187
188impl Encoder<()> for ecdsa::VerifyingKey<k256::Secp256k1> {
189    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
190        let mut out = ES256K.to_vec();
191        out.extend_from_slice(self.to_encoded_point(false).as_bytes());
192        Ok(out)
193    }
194}
195
196impl Encoder<()> for ecdsa::VerifyingKey<p256::NistP256> {
197    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
198        let mut out = ES256.to_vec();
199        out.extend_from_slice(self.to_encoded_point(false).as_bytes());
200        Ok(out)
201    }
202}
203
204impl Encoder<()> for ecdsa::VerifyingKey<p384::NistP384> {
205    fn encode(&self, _: ()) -> Result<Vec<u8>, Error> {
206        let mut out = ES384.to_vec();
207        out.extend_from_slice(self.to_encoded_point(false).as_bytes());
208        Ok(out)
209    }
210}
211
212pub struct Generate(Link<Vec<Uuid>>);
213
214#[async_trait::async_trait]
215impl Node for Generate {
216    fn to_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
217        self
218    }
219
220    fn parent(&self) -> Option<Arc<dyn Node>> {
221        self.0.parent.upgrade()
222    }
223
224    fn filetype(&self) -> FileType {
225        FileType::SocketDgram
226    }
227
228    fn id(&self) -> Arc<InodeId> {
229        self.0.inode.id.clone()
230    }
231
232    async fn open_dir(self: Arc<Self>) -> Result<Box<dyn WasiDir>, Error> {
233        Err(Error::not_dir())
234    }
235
236    async fn open_file(
237        self: Arc<Self>,
238        _path: &str,
239        dir: bool,
240        read: bool,
241        write: bool,
242        flags: FdFlags,
243    ) -> Result<Box<dyn WasiFile>, Error> {
244        if dir {
245            return Err(Error::not_dir());
246        }
247
248        if !read || !write {
249            return Err(Error::perm()); // FIXME: errno
250        }
251
252        if !flags.is_empty() {
253            return Err(Error::invalid_argument()); // FIXME: errno
254        }
255
256        Ok(Box::new(OpenGenerate {
257            _root: self.root(),
258            link: self,
259        }))
260    }
261}
262
263impl Generate {
264    pub fn new(parent: Arc<dyn Node>) -> Arc<Self> {
265        let id = parent.id().device().create_inode();
266
267        let inode = Inode {
268            data: Data::from(Vec::new()).into(),
269            id,
270        };
271
272        Arc::new(Self(Link {
273            parent: Arc::downgrade(&parent),
274            inode: inode.into(),
275        }))
276    }
277
278    async fn add<T, U, D, S>(self: &Arc<Generate>) -> Result<Uuid, Error>
279    where
280        T: Send + Sync + 'static,
281        U: Send + Sync + 'static,
282        D: Send + Sync + 'static,
283        S: Send + Sync + 'static,
284        T: RandomizedDigestSigner<D, S> + GenerateKey + ToPublic<Public = U>,
285        U: DigestVerifier<D, S> + Encoder<()>,
286        D: Digest + Clone,
287        S: Signature,
288    {
289        let parent = self
290            .parent()
291            .ok_or_else(Error::io)?
292            .to_any()
293            .downcast::<Directory>()
294            .map_err(|_| Error::io())?;
295
296        let secret = T::generate()?;
297        let public = secret.to_public();
298        let shared = public.encode(())?;
299        let uuid = uuid::Uuid::new_v4();
300
301        let d = Directory::new(parent.clone(), None);
302        d.attach("verify", Verify::new(d.clone(), public)).await?;
303        d.attach("share", Share::new(d.clone(), shared)).await?;
304        d.attach("sign", Sign::new(d.clone(), secret)).await?;
305        parent.attach(&uuid.to_string(), d).await?;
306
307        Ok(uuid)
308    }
309}
310
311struct OpenGenerate {
312    _root: Arc<dyn Node>,
313    link: Arc<Generate>,
314}
315
316#[async_trait::async_trait]
317impl WasiFile for OpenGenerate {
318    fn as_any(&self) -> &dyn Any {
319        self
320    }
321
322    async fn get_filetype(&mut self) -> Result<FileType, Error> {
323        Ok(FileType::SocketDgram)
324    }
325
326    async fn get_filestat(&mut self) -> Result<Filestat, Error> {
327        let ilock = self.link.0.inode.data.read().await;
328
329        Ok(Filestat {
330            device_id: **self.link.0.inode.id.device(),
331            inode: **self.link.0.inode.id,
332            filetype: FileType::SocketDgram,
333            nlink: Arc::strong_count(&self.link.0.inode) as u64,
334            size: 0,
335            atim: Some(ilock.access),
336            mtim: Some(ilock.modify),
337            ctim: Some(ilock.create),
338        })
339    }
340
341    async fn sock_recv<'a>(
342        &mut self,
343        bufs: &mut [IoSliceMut<'a>],
344        _flags: RiFlags,
345    ) -> Result<(u64, RoFlags), Error> {
346        let n = self.read_vectored(bufs).await?;
347        Ok((n, RoFlags::empty()))
348    }
349
350    async fn sock_send<'a>(&mut self, bufs: &[IoSlice<'a>], _flags: SiFlags) -> Result<u64, Error> {
351        self.write_vectored(bufs).await
352    }
353
354    async fn read_vectored<'a>(&mut self, bufs: &mut [IoSliceMut<'a>]) -> Result<u64, Error> {
355        let mut ilock = self.link.0.inode.data.write().await;
356
357        if let Some(uuid) = ilock.content.pop() {
358            let name = uuid.to_string();
359            let bytes = name.as_bytes();
360            let mut total = 0;
361
362            for buf in bufs {
363                let len = std::cmp::min(buf.len(), bytes.len() - total);
364                buf[..len].copy_from_slice(&bytes[total..][..len]);
365                total += len;
366            }
367
368            if total < bytes.len() {
369                ilock.content.push(uuid);
370                return Err(Error::too_big());
371            }
372
373            return Ok(total as u64);
374        }
375
376        Err(ErrorKind::WouldBlk.into())
377    }
378
379    async fn write_vectored<'a>(&mut self, bufs: &[IoSlice<'a>]) -> Result<u64, Error> {
380        if bufs.len() != 1 || bufs[0].len() != 4 {
381            return Err(Error::invalid_argument());
382        }
383
384        let uuid = match bufs[0].as_ref() {
385            RS256 => self.link.add::<Rs256, _, _, _>().await?,
386            RS384 => self.link.add::<Rs384, _, _, _>().await?,
387            RS512 => self.link.add::<Rs512, _, _, _>().await?,
388            PS256 => self.link.add::<Ps256, _, _, _>().await?,
389            PS384 => self.link.add::<Ps384, _, _, _>().await?,
390            PS512 => self.link.add::<Ps512, _, _, _>().await?,
391            ES256K => self.link.add::<Es256k, _, Sha256, _>().await?,
392            ES256 => self.link.add::<Es256, _, Sha256, _>().await?,
393            ES384 => self.link.add::<Es384, _, Sha384, _>().await?,
394            _ => return Err(ErrorKind::Ilseq.into()),
395        };
396
397        self.link.0.inode.data.write().await.content.push(uuid);
398        Ok(4)
399    }
400
401    async fn readable(&self) -> Result<(), Error> {
402        Ok(())
403    }
404
405    async fn writable(&self) -> Result<(), Error> {
406        Ok(())
407    }
408}