sos_vault/encoding/
vault.rs1use crate::{
2 Auth, Contents, Header, SharedAccess, Summary, Vault, VaultMeta,
3};
4use async_trait::async_trait;
5use binary_stream::futures::{
6 BinaryReader, BinaryWriter, Decodable, Encodable,
7};
8use sos_core::{
9 constants::VAULT_IDENTITY,
10 crypto::{AeadPack, Seed},
11 encoding::{decode_uuid, encoding_error},
12 file_identity::FileIdentity,
13 SecretId, UtcDateTime, VaultCommit, VaultFlags,
14};
15use std::io::{Error, Result, SeekFrom};
16use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
17
18#[async_trait]
19impl Encodable for VaultMeta {
20 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
21 &self,
22 writer: &mut BinaryWriter<W>,
23 ) -> Result<()> {
24 self.date_created.encode(&mut *writer).await?;
25 writer.write_string(&self.description).await?;
26 Ok(())
27 }
28}
29
30#[async_trait]
31impl Decodable for VaultMeta {
32 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
33 &mut self,
34 reader: &mut BinaryReader<R>,
35 ) -> Result<()> {
36 let mut date_created: UtcDateTime = Default::default();
37 date_created.decode(&mut *reader).await?;
38 self.description = reader.read_string().await?;
39 Ok(())
40 }
41}
42
43#[async_trait]
44impl Encodable for Auth {
45 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
46 &self,
47 writer: &mut BinaryWriter<W>,
48 ) -> Result<()> {
49 writer.write_bool(self.salt.is_some()).await?;
50 if let Some(salt) = &self.salt {
51 writer.write_string(salt).await?;
52 }
53 writer.write_bool(self.seed.is_some()).await?;
54 if let Some(seed) = &self.seed {
55 writer.write_bytes(seed).await?;
56 }
57 Ok(())
58 }
59}
60
61#[async_trait]
62impl Decodable for Auth {
63 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
64 &mut self,
65 reader: &mut BinaryReader<R>,
66 ) -> Result<()> {
67 let has_salt = reader.read_bool().await?;
68 if has_salt {
69 self.salt = Some(reader.read_string().await?);
70 }
71 let has_seed = reader.read_bool().await?;
72 if has_seed {
73 let bytes: [u8; Seed::SIZE] = reader
74 .read_bytes(Seed::SIZE)
75 .await?
76 .as_slice()
77 .try_into()
78 .map_err(encoding_error)?;
79 self.seed = Some(Seed(bytes));
80 }
81 Ok(())
82 }
83}
84
85#[async_trait]
86impl Encodable for Summary {
87 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
88 &self,
89 writer: &mut BinaryWriter<W>,
90 ) -> Result<()> {
91 writer.write_u16(self.version).await?;
92 self.cipher.encode(&mut *writer).await?;
93 self.kdf.encode(&mut *writer).await?;
94 writer.write_bytes(self.id.as_bytes()).await?;
95 writer.write_string(&self.name).await?;
96 writer.write_u64(self.flags.bits()).await?;
97 Ok(())
98 }
99}
100
101#[async_trait]
102impl Decodable for Summary {
103 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
104 &mut self,
105 reader: &mut BinaryReader<R>,
106 ) -> Result<()> {
107 self.version = reader.read_u16().await?;
108 self.cipher.decode(&mut *reader).await?;
109 self.kdf.decode(&mut *reader).await?;
110 self.id = decode_uuid(&mut *reader).await?;
111 self.name = reader.read_string().await?;
112 self.flags = VaultFlags::from_bits(reader.read_u64().await?)
113 .ok_or(crate::Error::InvalidVaultFlags)
114 .map_err(encoding_error)?;
115 Ok(())
116 }
117}
118
119#[async_trait]
120impl Encodable for Header {
121 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
122 &self,
123 writer: &mut BinaryWriter<W>,
124 ) -> Result<()> {
125 writer.write_bytes(&VAULT_IDENTITY).await?;
126
127 let size_pos = writer.stream_position().await?;
128 writer.write_u32(0).await?;
129
130 self.summary.encode(&mut *writer).await?;
131
132 writer.write_bool(self.meta.is_some()).await?;
133 if let Some(meta) = &self.meta {
134 meta.encode(&mut *writer).await?;
135 }
136
137 self.auth.encode(&mut *writer).await?;
138 self.shared_access.encode(&mut *writer).await?;
139
140 let header_pos = writer.stream_position().await?;
142 let header_len = header_pos - (size_pos + 4);
143
144 writer.seek(SeekFrom::Start(size_pos)).await?;
145 writer.write_u32(header_len as u32).await?;
146 writer.seek(SeekFrom::Start(header_pos)).await?;
147
148 Ok(())
149 }
150}
151
152#[async_trait]
153impl Decodable for Header {
154 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
155 &mut self,
156 reader: &mut BinaryReader<R>,
157 ) -> Result<()> {
158 FileIdentity::read_identity(&mut *reader, &VAULT_IDENTITY)
159 .await
160 .map_err(|_| Error::other("bad vault identity bytes"))?;
161
162 let _ = reader.read_u32().await?;
164
165 self.summary.decode(&mut *reader).await?;
166
167 let has_meta = reader.read_bool().await?;
168 if has_meta {
169 self.meta = Some(Default::default());
170 if let Some(meta) = self.meta.as_mut() {
171 meta.decode(&mut *reader).await?;
172 }
173 }
174
175 self.auth.decode(&mut *reader).await?;
176 self.shared_access.decode(&mut *reader).await?;
177
178 Ok(())
179 }
180}
181
182#[async_trait]
183impl Encodable for SharedAccess {
184 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
185 &self,
186 writer: &mut BinaryWriter<W>,
187 ) -> Result<()> {
188 match self {
189 SharedAccess::WriteAccess(recipients) => {
190 writer.write_u8(1).await?;
191 writer.write_u16(recipients.len() as u16).await?;
192 for recipient in recipients {
193 writer.write_string(recipient).await?;
194 }
195 }
196 SharedAccess::ReadOnly(aead) => {
197 writer.write_u8(2).await?;
198 aead.encode(writer).await?;
199 }
200 }
201
202 Ok(())
203 }
204}
205
206#[async_trait]
207impl Decodable for SharedAccess {
208 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
209 &mut self,
210 reader: &mut BinaryReader<R>,
211 ) -> Result<()> {
212 let id = reader.read_u8().await?;
213
214 match id {
215 1 => {
216 let mut recipients = Vec::new();
217 let length = reader.read_u16().await?;
218 for _ in 0..length {
219 let recipient = reader.read_string().await?;
220 let _: age::x25519::Recipient =
221 recipient.parse().map_err(|e: &str| {
222 Error::other(crate::Error::InvalidX25519Identity(
223 e.to_owned(),
224 ))
225 })?;
226 recipients.push(recipient);
227 }
228 *self = SharedAccess::WriteAccess(recipients);
229 }
230 2 => {
231 let mut aead: AeadPack = Default::default();
232 aead.decode(reader).await?;
233 *self = SharedAccess::ReadOnly(aead);
234 }
235 _ => {
236 return Err(encoding_error(
237 crate::Error::UnknownSharedAccessKind(id),
238 ));
239 }
240 }
241
242 Ok(())
243 }
244}
245
246impl Contents {
247 pub async fn encode_row<W: AsyncWrite + AsyncSeek + Unpin + Send>(
249 writer: &mut BinaryWriter<W>,
250 key: &SecretId,
251 row: &VaultCommit,
252 ) -> Result<()> {
253 let size_pos = writer.stream_position().await?;
254 writer.write_u32(0).await?;
255
256 writer.write_bytes(key.as_bytes()).await?;
257
258 row.encode(&mut *writer).await?;
259
260 let row_pos = writer.stream_position().await?;
262 let row_len = row_pos - (size_pos + 4);
263 writer.seek(SeekFrom::Start(size_pos)).await?;
264 writer.write_u32(row_len as u32).await?;
265 writer.seek(SeekFrom::Start(row_pos)).await?;
266
267 writer.write_u32(row_len as u32).await?;
270
271 Ok(())
272 }
273
274 pub async fn decode_row<R: AsyncRead + AsyncSeek + Unpin + Send>(
276 reader: &mut BinaryReader<R>,
277 ) -> Result<(SecretId, VaultCommit)> {
278 let _ = reader.read_u32().await?;
280
281 let uuid = decode_uuid(&mut *reader).await?;
282
283 let mut row: VaultCommit = Default::default();
284 row.decode(&mut *reader).await?;
285
286 let _ = reader.read_u32().await?;
288
289 Ok((uuid, row))
290 }
291}
292
293#[async_trait]
294impl Encodable for Contents {
295 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
296 &self,
297 writer: &mut BinaryWriter<W>,
298 ) -> Result<()> {
299 for (key, row) in &self.data {
300 Contents::encode_row(writer, key, row).await?;
301 }
302 Ok(())
303 }
304}
305
306#[async_trait]
307impl Decodable for Contents {
308 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
309 &mut self,
310 reader: &mut BinaryReader<R>,
311 ) -> Result<()> {
312 let mut pos = reader.stream_position().await?;
313 let len = reader.len().await?;
314 while pos < len {
315 let (uuid, value) = Contents::decode_row(reader).await?;
316 self.data.insert(uuid, value);
317 pos = reader.stream_position().await?;
318 }
319
320 Ok(())
321 }
322}
323
324#[async_trait]
325impl Encodable for Vault {
326 async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
327 &self,
328 writer: &mut BinaryWriter<W>,
329 ) -> Result<()> {
330 self.header.encode(writer).await?;
331 self.contents.encode(writer).await?;
332 Ok(())
333 }
334}
335
336#[async_trait]
337impl Decodable for Vault {
338 async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
339 &mut self,
340 reader: &mut BinaryReader<R>,
341 ) -> Result<()> {
342 self.header.decode(reader).await?;
343 self.contents.decode(reader).await?;
344 Ok(())
345 }
346}