| 
					
				 | 
			
			
				@@ -19,11 +19,11 @@ use brotli::{CompressorWriter, Decompressor}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use btserde::{self, read_from, write_to}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 mod crypto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use crypto::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    AsymKeyPub, Ciphertext, CredsPriv, Decrypter, Encrypter, EncrypterExt, Hash, HashKind, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    MerkleStream, SecretStream, Sign, Signature, Signer, SymKey, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    AsymKeyPub, Ciphertext, Creds, Decrypter, Encrypter, EncrypterExt, Hash, HashKind, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MerkleStream, SecretStream, Sign, Signature, Signer, SymKey, SymKeyKind, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use log::error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use log::{error, warn}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use serde::{de::DeserializeOwned, Deserialize, Serialize}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use serde_big_array::BigArray; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use std::{ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -40,7 +40,7 @@ use std::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Debug)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-enum Error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub enum Error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     MissingWritecap, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Io(std::io::Error), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Serde(btserde::Error), 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -177,9 +177,11 @@ impl<T, U: Decompose<T>, S: TryCompose<T, U, Error = Infallible>> Compose<T, U> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-trait HeaderAccess { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub trait HeaderAccess { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn block_key(&self) -> Result<SymKey>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Returns the integrity value used to protect the contents of the block. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn integrity(&self) -> Option<&[u8]>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /// Extensions to the `Read` trait. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -221,7 +223,7 @@ pub struct Header { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     readcaps: HashMap<Principal, Ciphertext<SymKey>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     writecap: Option<Writecap>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// A hash which provides integrity for the contents of the block body. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    integrity: Hash, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    integrity: Option<Hash>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Serialize, Deserialize, Default)] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -237,19 +239,35 @@ struct BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     creds: C, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-impl<T: Read + Seek, C> BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+impl<T: Read + Seek, C: Creds> BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn new(inner: T, creds: C) -> Result<BlockStream<T, C>> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let (trailered, trailer) = Trailered::new(inner)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let (trailered, trailer) = Trailered::<_, BlockTrailer>::new(inner)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let trailer = match trailer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Some(trailer) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                crypto::verify_header(&trailer.header, &trailer.sig)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trailer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            None => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let mut trailer = BlockTrailer::default(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let block_key = SymKey::generate(SymKeyKind::default())?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trailer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .header 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .readcaps 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .insert(creds.owner(), creds.ser_encrypt(&block_key)?); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // TODO: Insert writecap. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                trailer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Ok(BlockStream { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             trailered, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            trailer: trailer.unwrap_or_default(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            trailer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             header_buf: Vec::new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             creds, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-impl<C> BlockStream<File, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+impl<C: Creds> BlockStream<File, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn open<P: AsRef<std::path::Path>>(path: P, creds: C) -> Result<BlockStream<File, C>> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let inner = OpenOptions::new().read(true).write(true).open(path)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         BlockStream::new(inner, creds) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -272,7 +290,8 @@ impl<T: Write + Seek, C: Signer> Write for BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 impl<T: Write + Seek, C: Signer> WriteInteg for BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn flush_integ(&mut self, integrity: &[u8]) -> io::Result<()> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let header = &mut self.trailer.header; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        header.integrity.as_mut().copy_from_slice(integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let integ = header.integrity.get_or_insert_with(Hash::default); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        integ.as_mut().copy_from_slice(integrity); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.header_buf.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         write_to(&header, &mut self.header_buf).box_err()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.trailer.sig = self 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -314,6 +333,14 @@ impl<T, C: Decrypter + Owned> HeaderAccess for BlockStream<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.trailer.header.readcaps.insert(owner, readcap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Ok(()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn integrity(&self) -> Option<&[u8]> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.trailer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .header 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .integrity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .as_ref() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .map(|hash| hash.as_ref()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct BlockOpenOptions<T, C> { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -364,11 +391,12 @@ impl<T, C> BlockOpenOptions<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-impl<T: Read + Write + Seek + 'static, C: CredsPriv + Owned + 'static> BlockOpenOptions<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+impl<T: Read + Write + Seek + 'static, C: Creds + 'static> BlockOpenOptions<T, C> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn open(self) -> Result<Box<dyn Block>> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let stream = BlockStream::new(self.inner, self.creds)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let block_key = stream.block_key()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let stream = MerkleStream::new(stream)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut stream = MerkleStream::new(stream)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stream.assert_root_integrity()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if self.encrypt { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let stream = SecretStream::new(block_key).try_compose(stream)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let stream = SectoredBuf::new().try_compose(stream)?; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -619,19 +647,15 @@ impl<T> SectoredBuf<T> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 impl<T: Read + Seek> SectoredBuf<T> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// Fills the internal buffer by reading from the inner stream at the current position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// and updates `self.buf_start` with the position read from. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fn fill_internal_buf(&mut self) -> io::Result<usize> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn fill_internal_buf(&mut self) -> Result<usize> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.buf_start = self.inner.stream_position()?.try_into().box_err()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let read_bytes = if self.buf_start < self.len { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let read_bytes = self.inner.fill_buf(&mut self.buf)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if read_bytes < self.buf.len() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return Err(io::Error::new( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    io::ErrorKind::Other, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    format!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        "Failed to fill SectoredBuf.buf. Expected {} bytes, got {}.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        self.buf.len(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        read_bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return Err(Error::IncorrectSize { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    expected: self.buf.len(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    actual: read_bytes, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             read_bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -670,10 +694,15 @@ impl<T: Sectored + Read + Seek> TryCompose<T, SectoredBuf<T>> for SectoredBuf<() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         sectored.buf.resize(sect_sz, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let len_stored = match sectored.fill_internal_buf() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Ok(bytes_read) => bytes_read >= Self::RESERVED, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            Err(err) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                error!("SectoredBuf::fill_internal_buf returned an error: {}", err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Err(Error::IncorrectSize { actual, expected }) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if actual > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return Err(Error::IncorrectSize { expected, actual }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // When the actual size was 0 that just means the inner stream was empty, which is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // not an error. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Err(err) => return Err(err), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if len_stored { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if let Ok(len) = read_from::<u64, _>(&mut sectored.buf.as_slice()) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -756,6 +785,7 @@ impl<T: Seek + Read + Write> Write for SectoredBuf<T> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         write_to(&len, &mut self.buf.as_mut_slice()).box_err()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.inner.seek(SeekFrom::Start(0))?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.inner.write_all(&self.buf)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.flush()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // Seek to the next position. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.inner.seek(SeekFrom::Start(seek_to))?; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -786,7 +816,7 @@ impl<T: Read + Seek> Read for SectoredBuf<T> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 let byte_ct = match self.fill_internal_buf() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     Ok(byte_ct) => byte_ct, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     Err(err) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        error!("SectoredBuf::full_internal_buf returned an error: {}", err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        warn!("SectoredBuf::full_internal_buf returned an error: {}", err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -847,6 +877,10 @@ impl<T: HeaderAccess> HeaderAccess for SectoredBuf<T> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.inner.add_readcap_for(owner, key) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn integrity(&self) -> Option<&[u8]> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.integrity() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 impl<T: Read + Write + Seek + HeaderAccess> Block for SectoredBuf<T> {} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -946,7 +980,7 @@ impl FragmentRecord { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /// An identifier for a security principal, which is any entity that can be authenticated. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable, Clone, Default)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct Principal(Hash); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub struct Principal(Hash); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 impl Principal { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn kind(&self) -> HashKind { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1153,7 +1187,10 @@ struct FragmentSerial(u32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 mod tests { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     use std::io::Cursor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    use crate::crypto::{tpm::TpmCredStore, CredStore}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     use super::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    use tempdir::TempDir; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     use test_helpers::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fn path_from_str_test_case( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1603,4 +1640,60 @@ mod tests { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         assert_eq!(EXPECTED, actual); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[test] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn block_can_create_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let harness = SwtpmHarness::new().expect("failed to start swtpm"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let context = harness.context().expect("failed to retrieve context"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let cred_store = TpmCredStore::new(context, harness.state_path()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .expect("failed to create TpmCredStore"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let creds = cred_store.node_creds().expect("failed to get node creds"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BlockOpenOptions::new() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_inner(Cursor::new(Vec::<u8>::new())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_creds(creds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_encrypt(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .open() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .expect("failed to open block"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[test] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fn block_contents_persisted() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const EXPECTED: &[u8] = b"Silly sordid sulking sultans."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let temp_dir = TempDir::new("btlib").expect("failed to create temp dir"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let file_path = temp_dir.path().join("test.blk").to_owned(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let harness = SwtpmHarness::new().expect("failed to start swtpm"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let context = harness.context().expect("failed to retrieve context"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let cred_store = TpmCredStore::new(context, harness.state_path()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .expect("failed to create TpmCredStore"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let creds = cred_store.node_creds().expect("failed to get node creds"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let file = OpenOptions::new() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .create_new(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .write(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .read(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .open(&file_path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .expect("failed to open file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut block = BlockOpenOptions::new() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .with_inner(file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .with_creds(creds.clone()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .with_encrypt(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .open() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .expect("failed to open block"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            block.write(EXPECTED).expect("failed to write"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            block.flush().expect("flush failed"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let file = OpenOptions::new() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .read(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .open(&file_path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .expect("failed to reopen file"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut block = BlockOpenOptions::new() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_inner(file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_creds(creds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .with_encrypt(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .open() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .expect("failed to reopen block"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut actual = [0u8; EXPECTED.len()]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        block.read(&mut actual).expect("read failed"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert_eq!(EXPECTED, actual); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |