roaes/
lib.rs

1#![deny(warnings, missing_docs)]
2//! Library implementing the openaes standard used by the [Team Win Recovery Project (TWRP)][1], as
3//! of 2018-08-24.
4//!
5//! There are both implementations for reading (decrypting) and writing (encrypting)
6//! data. The intention is to make encrypted TWRP backups accessible or even facilitate
7//! re-compression with a different/more modern algorithm.
8//!
9//! [1]: <https://github.com/TeamWin/Team-Win-Recovery-Project/tree/58f2132bc3954fc704787d477500a209eedb8e29/openaes>
10
11use aes::cipher::generic_array::GenericArray;
12use aes::{Aes128, BlockCipher};
13pub use decrypt::RoaesSource;
14pub use encrypt::RoaesSink;
15use snafu::{Backtrace, GenerateBacktrace, Snafu};
16use std::io::ErrorKind as IOErrorKind;
17
18mod decrypt;
19mod encrypt;
20mod util;
21
22const OAES_BLOCK_SIZE: usize = 16;
23const OAES_BLOCK_SIZE64: u64 = OAES_BLOCK_SIZE as u64;
24const FILE_BLOCK_SIZE: usize = 4096;
25const FILE_BLOCK_SIZE64: u64 = FILE_BLOCK_SIZE as u64;
26
27type AesBlock = GenericArray<u8, <Aes128 as BlockCipher>::BlockSize>;
28
29/// Error type indicating errors and encapsulating errors from lower layers.
30#[allow(missing_docs)]
31#[derive(Debug, Snafu)]
32pub enum RoaesError {
33    /// No expected `OAES` magic number found in input for decryption.
34    NoMagicNumber,
35    /// End of file reached.
36    Eof,
37    /// Version, type, option or flag set to an unsupported value in the header.
38    Incompatible { desc: String, backtrace: Backtrace },
39    /// Error in underlying cryptography code.
40    Crypto {
41        source: Box<dyn std::error::Error + Send + Sync + 'static>,
42        backtrace: Backtrace,
43        desc: String,
44    },
45    /// General error.
46    General { backtrace: Backtrace, desc: String },
47    /// IO error
48    IO {
49        source: std::io::Error,
50        backtrace: Backtrace,
51        desc: String,
52    },
53}
54
55impl RoaesError {
56    fn underflow_multiple_aes_block(read: usize) -> Self {
57        RoaesError::IO {
58            source: std::io::Error::new(
59                IOErrorKind::UnexpectedEof,
60                "did not read multiple of AES block size",
61            ),
62            backtrace: Backtrace::generate(),
63            desc: format!(
64                "did not read multiple of AES block size, read: {} byte",
65                read
66            ),
67        }
68    }
69
70    fn general<S: Into<String>>(desc: S) -> Self {
71        RoaesError::General {
72            backtrace: Backtrace::generate(),
73            desc: desc.into(),
74        }
75    }
76
77    fn no_magic_number() -> Self {
78        RoaesError::NoMagicNumber {}
79    }
80
81    fn incompatibility<S: Into<String>>(desc: S) -> Self {
82        RoaesError::Incompatible {
83            backtrace: Backtrace::generate(),
84            desc: desc.into(),
85        }
86    }
87
88    fn crypto<E: std::error::Error + Send + Sync + 'static, S: Into<String>>(
89        err: E,
90        desc: S,
91    ) -> Self {
92        RoaesError::Crypto {
93            source: Box::new(err),
94            backtrace: Backtrace::generate(),
95            desc: desc.into(),
96        }
97    }
98
99    /// Checks error for indicating the absence of the `OAES` magic number.
100    pub fn is_no_valid_magic_number(&self) -> bool {
101        matches!(self, RoaesError::NoMagicNumber)
102    }
103}