secret_stream.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. pub use private::SecretStream;
  2. mod private {
  3. use crate::{
  4. crypto::{Error, Result, SymKey},
  5. Block, BlockMeta, Decompose, MetaAccess, Sectored, TryCompose,
  6. };
  7. use std::io::{self, Read, Seek, SeekFrom, Write};
  8. // A stream which encrypts all data written to it and decrypts all data read from it.
  9. pub struct SecretStream<T> {
  10. inner: T,
  11. // The sector size of the inner stream. Reads and writes are only executed using buffers of
  12. // this size.
  13. inner_sect_sz: usize,
  14. // The sector size of this stream. Reads and writes are only accepted for buffers of this size.
  15. sect_sz: usize,
  16. key: SymKey,
  17. /// Buffer for ciphertext.
  18. ct_buf: Vec<u8>,
  19. /// Buffer for plaintext.
  20. pt_buf: Vec<u8>,
  21. }
  22. impl<T> SecretStream<T> {
  23. /// Given an offset into this stream, produces the corresponding offset into the inner stream.
  24. fn inner_offset(&self, outer_offset: u64) -> u64 {
  25. let sect_sz = self.sect_sz as u64;
  26. let inner_sect_sz = self.inner_sect_sz as u64;
  27. // We return the offset into the current sector, plus the size of all previous sectors.
  28. outer_offset % sect_sz + outer_offset / sect_sz * inner_sect_sz
  29. }
  30. /// Given an offset into the inner stream, returns the corresponding offset into this stream.
  31. fn outer_offset(&self, inner_offset: u64) -> u64 {
  32. let sect_sz = self.sect_sz as u64;
  33. let inner_sect_sz = self.inner_sect_sz as u64;
  34. inner_offset % inner_sect_sz + inner_offset / inner_sect_sz * sect_sz
  35. }
  36. }
  37. impl SecretStream<()> {
  38. pub fn new(key: SymKey) -> SecretStream<()> {
  39. SecretStream {
  40. inner: (),
  41. inner_sect_sz: 0,
  42. sect_sz: 0,
  43. key,
  44. ct_buf: Vec::new(),
  45. pt_buf: Vec::new(),
  46. }
  47. }
  48. }
  49. impl<T> Decompose<T> for SecretStream<T> {
  50. fn into_inner(self) -> T {
  51. self.inner
  52. }
  53. }
  54. impl<T, U: Sectored> TryCompose<U, SecretStream<U>> for SecretStream<T> {
  55. type Error = Error;
  56. fn try_compose(mut self, inner: U) -> Result<SecretStream<U>> {
  57. let inner_sect_sz = inner.sector_sz();
  58. let expansion_sz = self.key.expansion_sz();
  59. let sect_sz = inner_sect_sz - expansion_sz;
  60. let block_sz = self.key.block_size();
  61. if 0 != sect_sz % block_sz {
  62. return Err(Error::IndivisibleSize {
  63. divisor: block_sz,
  64. actual: sect_sz,
  65. });
  66. }
  67. self.pt_buf.resize(inner_sect_sz, 0);
  68. self.pt_buf.resize(inner_sect_sz + block_sz, 0);
  69. Ok(SecretStream {
  70. inner,
  71. inner_sect_sz,
  72. sect_sz: inner_sect_sz - expansion_sz,
  73. key: self.key,
  74. ct_buf: self.ct_buf,
  75. pt_buf: self.pt_buf,
  76. })
  77. }
  78. }
  79. impl<T> Sectored for SecretStream<T> {
  80. fn sector_sz(&self) -> usize {
  81. self.sect_sz
  82. }
  83. }
  84. impl<T: Write> Write for SecretStream<T> {
  85. fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
  86. self.assert_sector_sz(buf.len())?;
  87. self.ct_buf.resize(self.inner_sect_sz, 0);
  88. let mut encrypter = self.key.to_encrypter()?;
  89. let mut count = encrypter.update(buf, &mut self.ct_buf)?;
  90. count += encrypter.finalize(&mut self.ct_buf[count..])?;
  91. self.ct_buf.truncate(count);
  92. self.inner.write_all(&self.ct_buf).map(|_| buf.len())
  93. }
  94. fn flush(&mut self) -> io::Result<()> {
  95. self.inner.flush()
  96. }
  97. }
  98. impl<T: Read> Read for SecretStream<T> {
  99. fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
  100. self.assert_sector_sz(buf.len())?;
  101. self.ct_buf.resize(self.inner_sect_sz, 0);
  102. match self.inner.read_exact(&mut self.ct_buf) {
  103. Ok(_) => (),
  104. Err(err) => {
  105. if err.kind() == io::ErrorKind::UnexpectedEof {
  106. return Ok(0);
  107. } else {
  108. return Err(err);
  109. }
  110. }
  111. }
  112. self.pt_buf
  113. .resize(self.inner_sect_sz + self.key.block_size(), 0);
  114. let mut decrypter = self.key.to_decrypter()?;
  115. let mut count = decrypter.update(&self.ct_buf, &mut self.pt_buf)?;
  116. count += decrypter.finalize(&mut self.pt_buf[count..])?;
  117. self.pt_buf.truncate(count);
  118. buf.copy_from_slice(&self.pt_buf);
  119. Ok(buf.len())
  120. }
  121. }
  122. impl<T: Seek> Seek for SecretStream<T> {
  123. fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
  124. let outer_offset = match pos {
  125. SeekFrom::Start(offset) => offset,
  126. SeekFrom::Current(offset) => {
  127. let inner_offset = self.inner.stream_position()?;
  128. let outer_offset = self.outer_offset(inner_offset);
  129. if offset >= 0 {
  130. outer_offset + offset as u64
  131. } else {
  132. outer_offset - (-offset as u64)
  133. }
  134. }
  135. SeekFrom::End(_) => {
  136. // We can support this once stream_len is stabilized:
  137. // https://github.com/rust-lang/rust/issues/59359
  138. return Err(io::Error::new(
  139. io::ErrorKind::Unsupported,
  140. "seeking from the end of the stream is not supported",
  141. ));
  142. }
  143. };
  144. let inner_offset = self.inner_offset(outer_offset);
  145. self.inner.seek(SeekFrom::Start(inner_offset))?;
  146. Ok(outer_offset)
  147. }
  148. }
  149. impl<T: AsRef<BlockMeta>> AsRef<BlockMeta> for SecretStream<T> {
  150. fn as_ref(&self) -> &BlockMeta {
  151. self.inner.as_ref()
  152. }
  153. }
  154. impl<T: AsMut<BlockMeta>> AsMut<BlockMeta> for SecretStream<T> {
  155. fn as_mut(&mut self) -> &mut BlockMeta {
  156. self.inner.as_mut()
  157. }
  158. }
  159. impl<T: MetaAccess> MetaAccess for SecretStream<T> {}
  160. impl<T: Block> Block for SecretStream<T> {
  161. fn flush_meta(&mut self) -> crate::Result<()> {
  162. self.inner.flush_meta()
  163. }
  164. }
  165. }
  166. #[cfg(test)]
  167. mod tests {
  168. use std::io::{Read, Seek, SeekFrom, Write};
  169. use crate::{
  170. crypto::{SymKey, SymKeyKind},
  171. test_helpers::{Randomizer, SectoredCursor},
  172. Sectored, TryCompose, SECTOR_SZ_DEFAULT,
  173. };
  174. use super::*;
  175. fn secret_stream_sequential_test_case(key: SymKey, inner_sect_sz: usize, sect_ct: usize) {
  176. let mut stream = SecretStream::new(key)
  177. .try_compose(SectoredCursor::new(
  178. vec![0u8; inner_sect_sz * sect_ct],
  179. inner_sect_sz,
  180. ))
  181. .expect("compose failed");
  182. let sector_sz = stream.sector_sz();
  183. for k in 0..sect_ct {
  184. let sector = vec![k as u8; sector_sz];
  185. stream.write(&sector).expect("write failed");
  186. }
  187. stream.seek(SeekFrom::Start(0)).expect("seek failed");
  188. for k in 0..sect_ct {
  189. let expected = vec![k as u8; sector_sz];
  190. let mut actual = vec![0u8; sector_sz];
  191. stream.read(&mut actual).expect("read failed");
  192. assert_eq!(expected, actual);
  193. }
  194. }
  195. fn secret_stream_sequential_test_suite(kind: SymKeyKind) {
  196. let key = SymKey::generate(kind).expect("key generation failed");
  197. secret_stream_sequential_test_case(key.clone(), SECTOR_SZ_DEFAULT, 16);
  198. }
  199. #[test]
  200. fn secret_stream_encrypt_decrypt_are_inverse_aes256cbc() {
  201. secret_stream_sequential_test_suite(SymKeyKind::Aes256Cbc)
  202. }
  203. #[test]
  204. fn secret_stream_encrypt_decrypt_are_inverse_aes256ctr() {
  205. secret_stream_sequential_test_suite(SymKeyKind::Aes256Ctr)
  206. }
  207. fn secret_stream_random_access_test_case(
  208. rando: Randomizer,
  209. key: SymKey,
  210. inner_sect_sz: usize,
  211. sect_ct: usize,
  212. ) {
  213. let mut stream = SecretStream::new(key)
  214. .try_compose(SectoredCursor::new(
  215. vec![0u8; inner_sect_sz * sect_ct],
  216. inner_sect_sz,
  217. ))
  218. .expect("compose failed");
  219. let sect_sz = stream.sector_sz();
  220. let indices: Vec<usize> = rando.take(sect_ct).map(|e| e % sect_ct).collect();
  221. for index in indices.iter().map(|e| *e) {
  222. let offset = index * sect_sz;
  223. stream
  224. .seek(SeekFrom::Start(offset as u64))
  225. .expect("seek to write failed");
  226. let sector = vec![index as u8; sect_sz];
  227. stream.write(&sector).expect("write failed");
  228. }
  229. for index in indices.iter().map(|e| *e) {
  230. let offset = index * sect_sz;
  231. stream
  232. .seek(SeekFrom::Start(offset as u64))
  233. .expect("seek to read failed");
  234. let expected = vec![index as u8; sect_sz];
  235. let mut actual = vec![0u8; sect_sz];
  236. stream.read(&mut actual).expect("read failed");
  237. assert_eq!(expected, actual);
  238. }
  239. }
  240. fn secret_stream_random_access_test_suite(kind: SymKeyKind) {
  241. const SEED: [u8; Randomizer::HASH.len()] = [3u8; Randomizer::HASH.len()];
  242. let key = SymKey::generate(kind).expect("key generation failed");
  243. secret_stream_random_access_test_case(
  244. Randomizer::new(SEED),
  245. key.clone(),
  246. SECTOR_SZ_DEFAULT,
  247. 20,
  248. );
  249. secret_stream_random_access_test_case(
  250. Randomizer::new(SEED),
  251. key.clone(),
  252. SECTOR_SZ_DEFAULT,
  253. 800,
  254. );
  255. secret_stream_random_access_test_case(Randomizer::new(SEED), key.clone(), 512, 200);
  256. secret_stream_random_access_test_case(Randomizer::new(SEED), key.clone(), 512, 20);
  257. secret_stream_random_access_test_case(Randomizer::new(SEED), key.clone(), 512, 200);
  258. }
  259. #[test]
  260. fn secret_stream_random_access() {
  261. secret_stream_random_access_test_suite(SymKeyKind::Aes256Cbc);
  262. secret_stream_random_access_test_suite(SymKeyKind::Aes256Ctr);
  263. }
  264. fn make_secret_stream(
  265. key_kind: SymKeyKind,
  266. num_sectors: usize,
  267. ) -> SecretStream<SectoredCursor<Vec<u8>>> {
  268. let key = SymKey::generate(key_kind).expect("key generation failed");
  269. let inner = SectoredCursor::new(
  270. vec![0u8; num_sectors * SECTOR_SZ_DEFAULT],
  271. SECTOR_SZ_DEFAULT,
  272. );
  273. SecretStream::new(key)
  274. .try_compose(inner)
  275. .expect("compose failed")
  276. }
  277. #[test]
  278. fn secret_stream_seek_from_start() {
  279. let mut stream = make_secret_stream(SymKeyKind::Aes256Cbc, 3);
  280. let sector_sz = stream.sector_sz();
  281. let expected = vec![2u8; sector_sz];
  282. // Write one sector of ones, one sector of twos and one sector of threes.
  283. for k in 1..4 {
  284. let sector: Vec<u8> = std::iter::repeat(k as u8).take(sector_sz).collect();
  285. stream.write(&sector).expect("writing to stream failed");
  286. }
  287. stream
  288. .seek(SeekFrom::Start(sector_sz as u64))
  289. .expect("seek failed");
  290. // A read from the stream should now return the second sector, which is filled with twos.
  291. let mut actual = vec![0u8; sector_sz];
  292. stream
  293. .read(&mut actual)
  294. .expect("reading from stream failed");
  295. assert_eq!(expected, actual);
  296. }
  297. #[test]
  298. fn secret_stream_seek_from_current() {
  299. let mut stream = make_secret_stream(SymKeyKind::Aes256Cbc, 3);
  300. let sector_sz = stream.sector_sz();
  301. let expected = vec![3u8; sector_sz];
  302. // Write one sector of ones, one sector of twos and one sector of threes.
  303. for k in 1..4 {
  304. let sector: Vec<u8> = std::iter::repeat(k as u8).take(sector_sz).collect();
  305. stream.write(&sector).expect("writing to stream failed");
  306. }
  307. stream
  308. .seek(SeekFrom::Current(-1 * (sector_sz as i64)))
  309. .expect("seek failed");
  310. // A read from the stream should now return the last sector, which is filled with threes.
  311. let mut actual = vec![0u8; sector_sz];
  312. stream
  313. .read(&mut actual)
  314. .expect("reading from stream failed");
  315. assert_eq!(expected, actual);
  316. }
  317. }