1#[cfg(feature = "compression-bzip2")]
4mod writer_bzip2;
5#[cfg(feature = "compression-bzip2")]
6pub use self::writer_bzip2::BZ;
7#[cfg(feature = "compression-deflate")]
8mod writer_deflate;
9#[cfg(feature = "compression-deflate")]
10pub use self::writer_deflate::{ZIP, ZLIB};
11
12use std::fmt;
13use std::io;
14
15use crate::armor;
16use crate::crypto::{aead, symmetric};
17use crate::types::{
18 AEADAlgorithm,
19 SymmetricAlgorithm,
20};
21use crate::{
22 Profile,
23 Result,
24 crypto::SessionKey,
25};
26use super::{Message, Cookie};
27
28impl<'a> Message<'a> {
29 pub(super) fn from(bs: BoxStack<'a, Cookie>) -> Self {
30 Message(bs)
31 }
32
33 pub(super) fn as_ref(&self) -> &BoxStack<'a, Cookie> {
34 &self.0
35 }
36
37 pub(super) fn as_mut(&mut self) -> &mut BoxStack<'a, Cookie> {
38 &mut self.0
39 }
40}
41
42impl<'a> io::Write for Message<'a> {
43 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
44 self.0.write(buf)
45 }
46
47 fn flush(&mut self) -> io::Result<()> {
48 self.0.flush()
49 }
50}
51
52impl<'a> From<Message<'a>> for BoxStack<'a, Cookie> {
53 fn from(s: Message<'a>) -> Self {
54 s.0
55 }
56}
57
58pub(crate) type BoxStack<'a, C> = Box<dyn Stackable<'a, C> + Send + Sync + 'a>;
59
60pub(crate) trait Stackable<'a, C> : io::Write + fmt::Debug {
62 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>>;
67
68 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>>;
74
75 fn mount(&mut self, new: BoxStack<'a, C>);
79
80 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)>;
86
87 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)>;
89
90 #[allow(dead_code)]
92 fn cookie_set(&mut self, cookie: C) -> C;
93
94 fn cookie_ref(&self) -> &C;
96
97 #[allow(dead_code)]
99 fn cookie_mut(&mut self) -> &mut C;
100
101 fn position(&self) -> u64;
103
104 fn write_u8(&mut self, b: u8) -> io::Result<()> {
106 self.write_all(&[b])
107 }
108}
109
110impl <'a, C> Stackable<'a, C> for BoxStack<'a, C> {
112 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
113 (*self).into_inner()
114 }
115 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
117 self.as_mut().pop()
118 }
119 fn mount(&mut self, new: BoxStack<'a, C>) {
121 self.as_mut().mount(new);
122 }
123 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)> {
124 self.as_mut().inner_mut()
125 }
126 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)> {
127 self.as_ref().inner_ref()
128 }
129 fn cookie_set(&mut self, cookie: C) -> C {
130 self.as_mut().cookie_set(cookie)
131 }
132 fn cookie_ref(&self) -> &C {
133 self.as_ref().cookie_ref()
134 }
135 fn cookie_mut(&mut self) -> &mut C {
136 self.as_mut().cookie_mut()
137 }
138 fn position(&self) -> u64 {
139 self.as_ref().position()
140 }
141}
142
143#[allow(dead_code)]
145pub(crate) fn map<C, F, T>(head: &(dyn Stackable<C> + Send + Sync),
146 mut fun: F) -> Option<T>
147where
148 F: FnMut(&(dyn Stackable<C> + Send + Sync)) -> Option<T>,
149{
150 let mut ow = Some(head);
151 while let Some(w) = ow {
152 if let Some(r) = fun(w) {
153 return Some(r);
154 }
155 ow = w.inner_ref()
156 }
157
158 None
159}
160
161#[allow(dead_code)]
163pub(crate) fn map_mut<C, F, T>(head: &mut (dyn Stackable<C> + Send + Sync),
164 mut fun: F) -> Option<T>
165where F: FnMut(&mut (dyn Stackable<C> + Send + Sync)) -> Option<T>
166{
167 let mut ow = Some(head);
168 while let Some(w) = ow {
169 if let Some(r) = fun(w) {
170 return Some(r);
171 }
172 ow = w.inner_mut()
173 }
174
175 None
176}
177
178#[allow(dead_code)]
180pub(crate) fn dump<C>(head: &(dyn Stackable<C> + Send + Sync)) {
181 let mut depth = 0;
182 map(head, |w| {
183 eprintln!("{}: {:?}", depth, w);
184 depth += 1;
185 Some(())
186 });
187}
188
189pub struct Identity<'a, C> {
191 inner: Option<BoxStack<'a, C>>,
192 cookie: C,
193}
194assert_send_and_sync!(Identity<'_, C> where C);
195
196impl<'a> Identity<'a, Cookie> {
197 pub fn new(inner: Message<'a>, cookie: Cookie)
199 -> Message<'a> {
200 Message::from(Box::new(Self{inner: Some(inner.into()), cookie }))
201 }
202}
203
204impl<'a, C> fmt::Debug for Identity<'a, C> {
205 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
206 f.debug_struct("Identity")
207 .field("inner", &self.inner)
208 .finish()
209 }
210}
211
212impl<'a, C> io::Write for Identity<'a, C> {
213 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
214 let writer = self.inner.as_mut()
215 .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe,
216 "Writer is finalized."))?;
217 writer.write(buf)
218 }
219
220 fn flush(&mut self) -> io::Result<()> {
221 let writer = self.inner.as_mut()
222 .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe,
223 "Writer is finalized."))?;
224 writer.flush()
225 }
226}
227
228impl<'a, C> Stackable<'a, C> for Identity<'a, C> {
229 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
231 Ok(self.inner)
232 }
233 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
235 Ok(self.inner.take())
236 }
237 fn mount(&mut self, new: BoxStack<'a, C>) {
239 self.inner = Some(new);
240 }
241 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)> {
242 if let Some(ref i) = self.inner {
243 Some(i)
244 } else {
245 None
246 }
247 }
248 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)> {
249 if let Some(ref mut i) = self.inner {
250 Some(i)
251 } else {
252 None
253 }
254 }
255 fn cookie_set(&mut self, cookie: C) -> C {
256 ::std::mem::replace(&mut self.cookie, cookie)
257 }
258 fn cookie_ref(&self) -> &C {
259 &self.cookie
260 }
261 fn cookie_mut(&mut self) -> &mut C {
262 &mut self.cookie
263 }
264 fn position(&self) -> u64 {
265 self.inner.as_ref().map(|i| i.position()).unwrap_or(0)
266 }
267}
268
269pub struct Generic<W: io::Write + Send + Sync, C> {
271 inner: W,
272 cookie: C,
273 position: u64,
274}
275assert_send_and_sync!(Generic<W, C> where W: io::Write, C);
276
277impl<'a, W: 'a + io::Write + Send + Sync> Generic<W, Cookie> {
278 pub fn new(inner: W, cookie: Cookie) -> Message<'a> {
280 Message::from(Box::new(Self::new_unboxed(inner, cookie)))
281 }
282
283 fn new_unboxed(inner: W, cookie: Cookie) -> Self {
284 Generic {
285 inner,
286 cookie,
287 position: 0,
288 }
289 }
290}
291
292impl<W: io::Write + Send + Sync, C> fmt::Debug for Generic<W, C> {
293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
294 f.debug_struct("writer::Generic")
295 .finish()
296 }
297}
298
299impl<W: io::Write + Send + Sync, C> io::Write for Generic<W, C> {
300 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
301 match self.inner.write(bytes) {
302 Ok(n) => {
303 self.position += n as u64;
304 Ok(n)
305 },
306 Err(e) => Err(e),
307 }
308 }
309
310 fn flush(&mut self) -> io::Result<()> {
311 self.inner.flush()
312 }
313}
314
315impl<'a, W: io::Write + Send + Sync, C> Stackable<'a, C> for Generic<W, C> {
316 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
318 Ok(None)
319 }
320 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
322 Ok(None)
323 }
324 fn mount(&mut self, _new: BoxStack<'a, C>) {
326 }
327 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)> {
328 None
333 }
334 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)> {
335 None
340 }
341 fn cookie_set(&mut self, cookie: C) -> C {
342 ::std::mem::replace(&mut self.cookie, cookie)
343 }
344 fn cookie_ref(&self) -> &C {
345 &self.cookie
346 }
347 fn cookie_mut(&mut self) -> &mut C {
348 &mut self.cookie
349 }
350 fn position(&self) -> u64 {
351 self.position
352 }
353}
354
355
356pub struct Armorer<'a, C: 'a> {
358 inner: Generic<armor::Writer<BoxStack<'a, C>>, C>,
359}
360assert_send_and_sync!(Armorer<'_, C> where C);
361
362impl<'a> Armorer<'a, Cookie> {
363 pub fn new<I, K, V>(inner: Message<'a>, cookie: Cookie,
365 kind: armor::Kind, headers: I)
366 -> Result<Message<'a>>
367 where I: IntoIterator<Item = (K, V)>,
368 K: AsRef<str>,
369 V: AsRef<str>,
370 {
371 Ok(Message::from(Box::new(Armorer {
372 inner: Generic::new_unboxed(
373 armor::Writer::with_headers(inner.into(), kind, headers)?,
374 cookie),
375 })))
376 }
377
378 pub fn set_profile(stack: &mut (dyn Stackable<'a, Cookie> + Send + Sync),
386 profile: Profile)
387 {
388 map_mut(stack, |w| match &mut w.cookie_mut().private {
389 super::Private::Armorer { set_profile, .. } => {
390 *set_profile = Some(profile);
391 Some(())
392 },
393 _ => None, });
395 }
396}
397
398impl<'a, C: 'a> fmt::Debug for Armorer<'a, C> {
399 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
400 f.debug_struct("writer::Armorer")
401 .field("inner", &self.inner)
402 .finish()
403 }
404}
405
406impl<'a> io::Write for Armorer<'a, Cookie> {
407 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
408 if bytes.len() == 0 {
409 return Ok(0);
410 }
411
412 if let Some(p) = match &mut self.cookie_mut().private {
414 super::Private::Armorer { set_profile } =>
415 set_profile.take(),
416 _ => None,
417 } {
418 let _ = self.inner.inner.set_profile(p);
419 }
420
421 self.inner.write(bytes)
422 }
423
424 fn flush(&mut self) -> io::Result<()> {
425 self.inner.flush()
426 }
427}
428
429impl<'a> Stackable<'a, Cookie> for Armorer<'a, Cookie> {
430 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, Cookie>>> {
431 let inner = self.inner.inner.finalize()?;
432 Ok(Some(inner))
433 }
434 fn pop(&mut self) -> Result<Option<BoxStack<'a, Cookie>>> {
435 unreachable!("Only implemented by Signer")
436 }
437 fn mount(&mut self, _new: BoxStack<'a, Cookie>) {
438 unreachable!("Only implemented by Signer")
439 }
440 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, Cookie> + Send + Sync)> {
441 Some(self.inner.inner.get_mut().as_mut())
442 }
443 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, Cookie> + Send + Sync)> {
444 Some(self.inner.inner.get_ref().as_ref())
445 }
446 fn cookie_set(&mut self, cookie: Cookie) -> Cookie {
447 self.inner.cookie_set(cookie)
448 }
449 fn cookie_ref(&self) -> &Cookie {
450 self.inner.cookie_ref()
451 }
452 fn cookie_mut(&mut self) -> &mut Cookie {
453 self.inner.cookie_mut()
454 }
455 fn position(&self) -> u64 {
456 self.inner.position
457 }
458}
459
460
461pub struct Encryptor<'a, C: 'a> {
463 inner: Generic<symmetric::Encryptor<Box<dyn Stackable<'a, C> + Send + Sync + 'a>>, C>,
464}
465assert_send_and_sync!(Encryptor<'_, C> where C);
466
467impl<'a> Encryptor<'a, Cookie> {
468 pub fn new(inner: Message<'a>, cookie: Cookie, algo: SymmetricAlgorithm,
470 key: &SessionKey)
471 -> Result<Message<'a>>
472 {
473 use crate::crypto::symmetric::{
474 BlockCipherMode,
475 PaddingMode,
476 };
477
478 Ok(Message::from(Box::new(Encryptor {
479 inner: Generic::new_unboxed(
480 symmetric::Encryptor::new(
481 algo, BlockCipherMode::CFB, PaddingMode::None,
482 key, None, inner.into())?,
483 cookie),
484 })))
485 }
486}
487
488impl<'a, C: 'a> fmt::Debug for Encryptor<'a, C> {
489 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490 f.debug_struct("writer::Encryptor")
491 .field("inner", &self.inner)
492 .finish()
493 }
494}
495
496impl<'a, C: 'a> io::Write for Encryptor<'a, C> {
497 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
498 self.inner.write(bytes)
499 }
500
501 fn flush(&mut self) -> io::Result<()> {
502 self.inner.flush()
503 }
504}
505
506impl<'a, C: 'a> Stackable<'a, C> for Encryptor<'a, C> {
507 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
508 let inner = self.inner.inner.finalize()?;
509 Ok(Some(inner))
510 }
511 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
512 unreachable!("Only implemented by Signer")
513 }
514 fn mount(&mut self, _new: BoxStack<'a, C>) {
515 unreachable!("Only implemented by Signer")
516 }
517 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)> {
518 None
521 }
522 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)> {
523 self.inner.inner.get_ref().map(|r| r.as_ref())
524 }
525 fn cookie_set(&mut self, cookie: C) -> C {
526 self.inner.cookie_set(cookie)
527 }
528 fn cookie_ref(&self) -> &C {
529 self.inner.cookie_ref()
530 }
531 fn cookie_mut(&mut self) -> &mut C {
532 self.inner.cookie_mut()
533 }
534 fn position(&self) -> u64 {
535 self.inner.position
536 }
537}
538
539
540pub struct AEADEncryptor<'a, 's, C: 'a> {
542 inner: Generic<aead::Encryptor<'s, BoxStack<'a, C>>, C>,
543}
544assert_send_and_sync!(AEADEncryptor<'_, '_, C> where C);
545
546impl<'a, 's> AEADEncryptor<'a, 's, Cookie> {
547 pub fn new<S>(inner: Message<'a>, cookie: Cookie,
549 cipher: SymmetricAlgorithm, aead: AEADAlgorithm,
550 chunk_size: usize, schedule: S)
551 -> Result<Message<'a>>
552 where
553 S: aead::Schedule<aead::EncryptionContext> + 'a + 's,
554 {
555 Ok(Message::from(Box::new(AEADEncryptor {
556 inner: Generic::new_unboxed(
557 aead::Encryptor::new(cipher, aead, chunk_size, schedule,
558 inner.into())?,
559 cookie),
560 })))
561 }
562}
563
564impl<'a, C: 'a> fmt::Debug for AEADEncryptor<'a, '_, C> {
565 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
566 f.debug_struct("writer::AEADEncryptor")
567 .field("inner", &self.inner)
568 .finish()
569 }
570}
571
572impl<'a, C: 'a> io::Write for AEADEncryptor<'a, '_, C> {
573 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
574 self.inner.write(bytes)
575 }
576
577 fn flush(&mut self) -> io::Result<()> {
578 self.inner.flush()
579 }
580}
581
582impl<'a, C: 'a> Stackable<'a, C> for AEADEncryptor<'a, '_, C> {
583 fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
584 let inner = self.inner.inner.finalize()?;
585 Ok(Some(inner))
586 }
587 fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
588 unreachable!("Only implemented by Signer")
589 }
590 fn mount(&mut self, _new: BoxStack<'a, C>) {
591 unreachable!("Only implemented by Signer")
592 }
593 fn inner_mut(&mut self) -> Option<&mut (dyn Stackable<'a, C> + Send + Sync)> {
594 None
597 }
598 fn inner_ref(&self) -> Option<&(dyn Stackable<'a, C> + Send + Sync)> {
599 self.inner.inner.get_ref().map(|r| r.as_ref())
600 }
601 fn cookie_set(&mut self, cookie: C) -> C {
602 self.inner.cookie_set(cookie)
603 }
604 fn cookie_ref(&self) -> &C {
605 self.inner.cookie_ref()
606 }
607 fn cookie_mut(&mut self) -> &mut C {
608 self.inner.cookie_mut()
609 }
610 fn position(&self) -> u64 {
611 self.inner.position
612 }
613}
614
615#[cfg(test)]
616mod test {
617 use std::io::Write;
618 use super::*;
619
620 #[test]
621 fn generic_writer() {
622 let mut inner = Vec::new();
623 {
624 let mut w = Generic::new(&mut inner, Cookie::new(0));
625 assert_eq!(w.as_ref().cookie_ref().level, 0);
626 dump(w.as_ref());
627
628 *w.as_mut().cookie_mut() = Cookie::new(1);
629 assert_eq!(w.as_ref().cookie_ref().level, 1);
630
631 w.write_all(b"be happy").unwrap();
632 let mut count = 0;
633 map_mut(w.as_mut(), |g| -> Option<()> {
634 let new = Cookie::new(0);
635 let old = g.cookie_set(new);
636 assert_eq!(old.level, 1);
637 count += 1;
638 None
639 });
640 assert_eq!(count, 1);
641 assert_eq!(w.as_ref().cookie_ref().level, 0);
642 }
643 assert_eq!(&inner, b"be happy");
644 }
645
646 #[test]
647 fn stack() {
648 let mut inner = Vec::new();
649 {
650 let w = Generic::new(&mut inner, Cookie::new(0));
651 dump(w.as_ref());
652
653 let w = Identity::new(w, Cookie::new(0));
654 dump(w.as_ref());
655
656 let mut count = 0;
657 map(w.as_ref(), |g| -> Option<()> {
658 assert_eq!(g.cookie_ref().level, 0);
659 count += 1;
660 None
661 });
662 assert_eq!(count, 2);
663 }
664 }
665}