Преглед изворни кода

Renamed a few items in btlib.

Matthew Carr пре 2 година
родитељ
комит
2ebb8a67ed
4 измењених фајлова са 65 додато и 79 уклоњено
  1. 5 7
      crates/btlib/TODO.txt
  2. 10 11
      crates/btlib/src/crypto/mod.rs
  3. 47 58
      crates/btlib/src/lib.rs
  4. 3 3
      crates/btlib/src/test_helpers.rs

+ 5 - 7
crates/btlib/TODO.txt

@@ -1,6 +1,3 @@
-Write more tests which exercise the creation, writing and reading of blocks, including those
-persisted to the filesystem.
-
 Fix BufSectored so it doesn't have to write to the first sector every flush.
 
 Track position and dirty-ness in Trailered.
@@ -15,16 +12,17 @@ Move crypto::{encrypt, decrypt} into corresponding {EncrypterExt, DecrypterExt}.
 Create an enum to eliminate the use of Block trait objects?
 
 Add a ser_sign_into method to SignerExt which serializes a value into a provided Vec<u8> and returns
-a signature over this data.
+a signature over this data. Update BlockStream::flush_integ to use this method.
 
 Convert all sector sizes to u64 for portability.
 
 Create an extension trait for u64 with a method for adding an i64 to it. Use this in
-SecretStream::seek and Trailered::seek.
-
-Create a full-duplex stream for compressing and decompressing data.
+SecretStream::seek, Trailered::seek and SectoredBuf::seek.
 
 Create a struct which digests data written to it before passing it to an underlying Write.
 
 Fix bug where writing to a block that already has a Writecap in its header using the creds of
 a different node produces an invalid signature (a signature using the creds of the other node).
+
+Create a struct called WritecapBody to contain the fields of Writecap which go into the signature
+calculation so that WritecapSigInput is no longer required.

+ 10 - 11
crates/btlib/src/crypto/mod.rs

@@ -2,11 +2,10 @@
 ///
 pub mod tpm;
 
-use crate::{Block, BoxInIoErr, Decompose, HeaderAccess, Trailered, WriteInteg, SECTOR_SZ_DEFAULT};
-
-use super::{
-    fmt, io, BigArray, Deserialize, Display, Epoch, Formatter, Hashable, Header, Path, Principal,
-    Principaled, Read, Sectored, Seek, Serialize, TryCompose, Write, Writecap,
+use crate::{
+    fmt, io, BigArray, Block, BlockMetaBody, BoxInIoErr, Decompose, Deserialize, Display, Epoch,
+    Formatter, Hashable, MetaAccess, Path, Principal, Principaled, Read, Sectored, Seek, Serialize,
+    Trailered, TryCompose, Write, WriteInteg, Writecap, SECTOR_SZ_DEFAULT,
 };
 
 use btserde::{self, from_vec, to_vec, write_to};
@@ -1816,7 +1815,7 @@ pub struct MerkleStream<T> {
     pos: usize,
 }
 
-impl<T: HeaderAccess> MerkleStream<T> {
+impl<T: MetaAccess> MerkleStream<T> {
     /// Asserts that the root merkle node contains the integrity value given by the inner stream.
     pub fn assert_root_integrity(&mut self) -> Result<()> {
         let hash_data = self.trailered.inner.integrity();
@@ -1907,7 +1906,7 @@ impl<T: Seek> Seek for MerkleStream<T> {
     }
 }
 
-impl<T: HeaderAccess> HeaderAccess for MerkleStream<T> {
+impl<T: MetaAccess> MetaAccess for MerkleStream<T> {
     fn block_key(&self) -> crate::Result<SymKey> {
         self.trailered.inner.block_key()
     }
@@ -2082,7 +2081,7 @@ impl<T: Seek> Seek for SecretStream<T> {
     }
 }
 
-impl<T: HeaderAccess> HeaderAccess for SecretStream<T> {
+impl<T: MetaAccess> MetaAccess for SecretStream<T> {
     fn block_key(&self) -> crate::Result<SymKey> {
         self.inner.block_key()
     }
@@ -2100,7 +2099,7 @@ impl<T: HeaderAccess> HeaderAccess for SecretStream<T> {
     }
 }
 
-impl<T: Read + Write + Seek + HeaderAccess> Block for SecretStream<T> {}
+impl<T: Read + Write + Seek + MetaAccess> Block for SecretStream<T> {}
 
 pub(crate) fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Ciphertext<T>> {
     let data = to_vec(value)?;
@@ -2117,12 +2116,12 @@ pub(crate) fn decrypt<T: DeserializeOwned, K: Decrypter>(
     Ok(from_vec(&plaintext)?)
 }
 
-pub(crate) fn sign_header<K: Signer>(header: &Header, signer: &K) -> Result<Signature> {
+pub(crate) fn sign_header<K: Signer>(header: &BlockMetaBody, signer: &K) -> Result<Signature> {
     let header = to_vec(&header)?;
     signer.sign(std::iter::once(header.as_slice()))
 }
 
-pub(crate) fn verify_header(header: &Header, sig: &Signature) -> Result<()> {
+pub(crate) fn verify_header(header: &BlockMetaBody, sig: &Signature) -> Result<()> {
     let writecap = header
         .writecap
         .as_ref()

+ 47 - 58
crates/btlib/src/lib.rs

@@ -7,9 +7,6 @@ mod crypto;
 #[cfg(test)]
 mod test_helpers;
 
-#[cfg(test)]
-mod serde_tests;
-
 #[macro_use]
 extern crate static_assertions;
 
@@ -31,7 +28,6 @@ use std::{
     collections::HashMap,
     convert::{Infallible, TryFrom},
     fmt::{self, Display, Formatter},
-    fs::{File, OpenOptions},
     hash::Hash as Hashable,
     io::{self, Read, Seek, SeekFrom, Write},
     marker::PhantomData,
@@ -133,9 +129,11 @@ impl<T, E: Display> StrInIoErr<T> for std::result::Result<T, E> {
     }
 }
 
+/// The default sector size to use for new blocks.
 const SECTOR_SZ_DEFAULT: usize = 4096;
 
-trait Block: Read + Write + Seek + HeaderAccess {}
+/// Trait for types which provide read and write access to blocks.
+pub trait Block: Read + Write + Seek + MetaAccess {}
 
 // A trait for streams which only allow reads and writes in fixed sized units called sectors.
 trait Sectored {
@@ -178,7 +176,7 @@ impl<T, U: Decompose<T>, S: TryCompose<T, U, Error = Infallible>> Compose<T, U>
     }
 }
 
-pub trait HeaderAccess {
+pub trait MetaAccess {
     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.
@@ -219,8 +217,11 @@ trait ReadExt: Read {
 
 impl<T: Read> ReadExt for T {}
 
+/// This struct contains all of the metadata fields associated with a block, except for its
+/// signature. Since this struct implements `Serialize`, this allows for convenient signature
+/// calculations.
 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
-pub struct Header {
+pub struct BlockMetaBody {
     path: Path,
     readcaps: HashMap<Principal, Ciphertext<SymKey>>,
     writecap: Option<Writecap>,
@@ -230,9 +231,9 @@ pub struct Header {
     signing_key: AsymKeyPub<Sign>,
 }
 
-impl Header {
-    fn new<C: Creds>(creds: &C) -> Header {
-        Header {
+impl BlockMetaBody {
+    fn new<C: Creds>(creds: &C) -> BlockMetaBody {
+        BlockMetaBody {
             path: Path::default(),
             readcaps: HashMap::new(),
             writecap: creds.writecap().map(|e| e.to_owned()),
@@ -242,62 +243,55 @@ impl Header {
     }
 }
 
+/// Signed metadata associated with a block.
 #[derive(Serialize, Deserialize)]
-struct BlockTrailer {
-    header: Header,
+struct BlockMeta {
+    body: BlockMetaBody,
     sig: Signature,
 }
 
-impl BlockTrailer {
-    fn new<C: Creds>(creds: &C) -> BlockTrailer {
-        let header = Header::new(creds);
-        let sig = Signature::empty(header.signing_key.scheme());
-        BlockTrailer { header, sig }
+impl BlockMeta {
+    fn new<C: Creds>(creds: &C) -> BlockMeta {
+        let body = BlockMetaBody::new(creds);
+        let sig = Signature::empty(body.signing_key.scheme());
+        BlockMeta { body, sig }
     }
 }
 
 struct BlockStream<T, C> {
-    trailered: Trailered<T, BlockTrailer>,
-    trailer: BlockTrailer,
-    header_buf: Vec<u8>,
+    trailered: Trailered<T, BlockMeta>,
+    meta: BlockMeta,
+    meta_body_buf: Vec<u8>,
     creds: C,
 }
 
 impl<T: Read + Seek, C: Creds> BlockStream<T, C> {
     fn new(inner: T, creds: C) -> Result<BlockStream<T, C>> {
-        let (trailered, trailer) = Trailered::<_, BlockTrailer>::new(inner)?;
+        let (trailered, trailer) = Trailered::<_, BlockMeta>::new(inner)?;
         let trailer = match trailer {
             Some(trailer) => {
-                crypto::verify_header(&trailer.header, &trailer.sig)?;
+                crypto::verify_header(&trailer.body, &trailer.sig)?;
                 trailer
             }
             None => {
-                let mut trailer = BlockTrailer::new(&creds);
+                let mut meta = BlockMeta::new(&creds);
                 let block_key = SymKey::generate(SymKeyKind::default())?;
-                trailer
-                    .header
+                meta.body
                     .readcaps
                     .insert(creds.principal(), creds.ser_encrypt(&block_key)?);
-                trailer.header.writecap = creds.writecap().map(|e| e.to_owned());
-                trailer
+                meta.body.writecap = creds.writecap().map(|e| e.to_owned());
+                meta
             }
         };
         Ok(BlockStream {
             trailered,
-            trailer,
-            header_buf: Vec::new(),
+            meta: trailer,
+            meta_body_buf: Vec::new(),
             creds,
         })
     }
 }
 
-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)
-    }
-}
-
 impl<T: Write + Seek, C: Signer> Write for BlockStream<T, C> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.trailered.write(buf)
@@ -313,15 +307,15 @@ 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;
-        let integ = header.integrity.get_or_insert_with(Hash::default);
+        let meta_body = &mut self.meta.body;
+        let integ = meta_body.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
+        self.meta_body_buf.clear();
+        write_to(&meta_body, &mut self.meta_body_buf).box_err()?;
+        self.meta.sig = self
             .creds
-            .sign(std::iter::once(self.header_buf.as_slice()))?;
-        self.trailered.flush(&self.trailer)?;
+            .sign(std::iter::once(self.meta_body_buf.as_slice()))?;
+        self.trailered.flush(&self.meta)?;
         Ok(())
     }
 }
@@ -340,11 +334,11 @@ impl<T: Seek, C> Seek for BlockStream<T, C> {
     }
 }
 
-impl<T, C: Decrypter + Principaled> HeaderAccess for BlockStream<T, C> {
+impl<T, C: Decrypter + Principaled> MetaAccess for BlockStream<T, C> {
     fn block_key(&self) -> Result<SymKey> {
         let readcap = self
-            .trailer
-            .header
+            .meta
+            .body
             .readcaps
             .get(&self.creds.principal())
             .ok_or(Error::Crypto(crypto::Error::NoReadCap))?;
@@ -354,20 +348,16 @@ impl<T, C: Decrypter + Principaled> HeaderAccess for BlockStream<T, C> {
     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()> {
         let block_key = self.block_key()?;
         let readcap = key.ser_encrypt(&block_key)?;
-        self.trailer.header.readcaps.insert(owner, readcap);
+        self.meta.body.readcaps.insert(owner, readcap);
         Ok(())
     }
 
     fn integrity(&self) -> Option<&[u8]> {
-        self.trailer
-            .header
-            .integrity
-            .as_ref()
-            .map(|hash| hash.as_ref())
+        self.meta.body.integrity.as_ref().map(|hash| hash.as_ref())
     }
 
     fn set_path(&mut self, path: Path) {
-        self.trailer.header.path = path;
+        self.meta.body.path = path;
     }
 }
 
@@ -897,7 +887,7 @@ impl<T: Seek + Read + Write> Seek for SectoredBuf<T> {
     }
 }
 
-impl<T: HeaderAccess> HeaderAccess for SectoredBuf<T> {
+impl<T: MetaAccess> MetaAccess for SectoredBuf<T> {
     fn block_key(&self) -> Result<SymKey> {
         self.inner.block_key()
     }
@@ -915,7 +905,7 @@ impl<T: HeaderAccess> HeaderAccess for SectoredBuf<T> {
     }
 }
 
-impl<T: Read + Write + Seek + HeaderAccess> Block for SectoredBuf<T> {}
+impl<T: Read + Write + Seek + MetaAccess> Block for SectoredBuf<T> {}
 
 /// An envelopment of a key, which is tagged with the principal who the key is meant for.
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
@@ -1217,7 +1207,7 @@ struct FragmentSerial(u32);
 
 #[cfg(test)]
 mod tests {
-    use std::io::Cursor;
+    use std::{fs::OpenOptions, io::Cursor};
 
     use crate::crypto::{tpm::TpmCredStore, CredStore, CredsPriv};
 
@@ -1691,7 +1681,6 @@ mod tests {
     #[test]
     fn block_contents_persisted() {
         const EXPECTED: &[u8] = b"Silly sordid sulking sultans.";
-        const PASSWORD: &str = "(1337Prestidigitation7331)";
         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");
@@ -1699,7 +1688,7 @@ mod tests {
         let cred_store = TpmCredStore::new(context, harness.state_path())
             .expect("failed to create TpmCredStore");
         let root_creds = cred_store
-            .gen_root_creds(PASSWORD)
+            .gen_root_creds("(1337Prestidigitation7331)")
             .expect("failed to get root creds");
         let mut node_creds = cred_store.node_creds().expect("failed to get node creds");
         let writecap = root_creds

+ 3 - 3
crates/btlib/src/test_helpers.rs

@@ -198,7 +198,7 @@ pub(crate) fn make_block_with(readcap: Readcap) -> Box<dyn Block> {
     // would be invalid.
     let (writecap, creds) = make_writecap_and_creds(vec!["apps"]);
     let root_writecap = writecap.next.as_ref().unwrap();
-    let header = Header {
+    let header = BlockMetaBody {
         path: make_path_with_root(root_writecap.issued_to.clone(), vec!["apps", "verse"]),
         readcaps,
         writecap: Some(writecap),
@@ -208,8 +208,8 @@ pub(crate) fn make_block_with(readcap: Readcap) -> Box<dyn Block> {
     let sig = Signature::copy_from(Sign::RSA_PSS_3072_SHA_256, &SIGNATURE);
     let mut stream =
         BlockStream::new(BtCursor::new(Vec::new()), creds).expect("create block stream failed");
-    stream.trailer.header = header;
-    stream.trailer.sig = sig;
+    stream.meta.body = header;
+    stream.meta.sig = sig;
     let block_key = stream.block_key().expect("get block key failed");
     let stream = MerkleStream::new(stream).expect("create merkle stream failed");
     let stream = SecretStream::new(block_key)