Przeglądaj źródła

Renamed a few items in btlib.

Matthew Carr 2 lat temu
rodzic
commit
2ebb8a67ed

+ 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.
 Fix BufSectored so it doesn't have to write to the first sector every flush.
 
 
 Track position and dirty-ness in Trailered.
 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?
 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
 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.
 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
 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.
 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
 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).
 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;
 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};
 use btserde::{self, from_vec, to_vec, write_to};
@@ -1816,7 +1815,7 @@ pub struct MerkleStream<T> {
     pos: usize,
     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.
     /// Asserts that the root merkle node contains the integrity value given by the inner stream.
     pub fn assert_root_integrity(&mut self) -> Result<()> {
     pub fn assert_root_integrity(&mut self) -> Result<()> {
         let hash_data = self.trailered.inner.integrity();
         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> {
     fn block_key(&self) -> crate::Result<SymKey> {
         self.trailered.inner.block_key()
         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> {
     fn block_key(&self) -> crate::Result<SymKey> {
         self.inner.block_key()
         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>> {
 pub(crate) fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Ciphertext<T>> {
     let data = to_vec(value)?;
     let data = to_vec(value)?;
@@ -2117,12 +2116,12 @@ pub(crate) fn decrypt<T: DeserializeOwned, K: Decrypter>(
     Ok(from_vec(&plaintext)?)
     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)?;
     let header = to_vec(&header)?;
     signer.sign(std::iter::once(header.as_slice()))
     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
     let writecap = header
         .writecap
         .writecap
         .as_ref()
         .as_ref()

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

@@ -7,9 +7,6 @@ mod crypto;
 #[cfg(test)]
 #[cfg(test)]
 mod test_helpers;
 mod test_helpers;
 
 
-#[cfg(test)]
-mod serde_tests;
-
 #[macro_use]
 #[macro_use]
 extern crate static_assertions;
 extern crate static_assertions;
 
 
@@ -31,7 +28,6 @@ use std::{
     collections::HashMap,
     collections::HashMap,
     convert::{Infallible, TryFrom},
     convert::{Infallible, TryFrom},
     fmt::{self, Display, Formatter},
     fmt::{self, Display, Formatter},
-    fs::{File, OpenOptions},
     hash::Hash as Hashable,
     hash::Hash as Hashable,
     io::{self, Read, Seek, SeekFrom, Write},
     io::{self, Read, Seek, SeekFrom, Write},
     marker::PhantomData,
     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;
 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.
 // A trait for streams which only allow reads and writes in fixed sized units called sectors.
 trait Sectored {
 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 block_key(&self) -> Result<SymKey>;
     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()>;
     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()>;
     /// Returns the integrity value used to protect the contents of the block.
     /// 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 {}
 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)]
 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
-pub struct Header {
+pub struct BlockMetaBody {
     path: Path,
     path: Path,
     readcaps: HashMap<Principal, Ciphertext<SymKey>>,
     readcaps: HashMap<Principal, Ciphertext<SymKey>>,
     writecap: Option<Writecap>,
     writecap: Option<Writecap>,
@@ -230,9 +231,9 @@ pub struct Header {
     signing_key: AsymKeyPub<Sign>,
     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(),
             path: Path::default(),
             readcaps: HashMap::new(),
             readcaps: HashMap::new(),
             writecap: creds.writecap().map(|e| e.to_owned()),
             writecap: creds.writecap().map(|e| e.to_owned()),
@@ -242,62 +243,55 @@ impl Header {
     }
     }
 }
 }
 
 
+/// Signed metadata associated with a block.
 #[derive(Serialize, Deserialize)]
 #[derive(Serialize, Deserialize)]
-struct BlockTrailer {
-    header: Header,
+struct BlockMeta {
+    body: BlockMetaBody,
     sig: Signature,
     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> {
 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,
     creds: C,
 }
 }
 
 
 impl<T: Read + Seek, C: Creds> BlockStream<T, C> {
 impl<T: Read + Seek, C: Creds> BlockStream<T, C> {
     fn new(inner: T, creds: C) -> Result<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 {
         let trailer = match trailer {
             Some(trailer) => {
             Some(trailer) => {
-                crypto::verify_header(&trailer.header, &trailer.sig)?;
+                crypto::verify_header(&trailer.body, &trailer.sig)?;
                 trailer
                 trailer
             }
             }
             None => {
             None => {
-                let mut trailer = BlockTrailer::new(&creds);
+                let mut meta = BlockMeta::new(&creds);
                 let block_key = SymKey::generate(SymKeyKind::default())?;
                 let block_key = SymKey::generate(SymKeyKind::default())?;
-                trailer
-                    .header
+                meta.body
                     .readcaps
                     .readcaps
                     .insert(creds.principal(), creds.ser_encrypt(&block_key)?);
                     .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 {
         Ok(BlockStream {
             trailered,
             trailered,
-            trailer,
-            header_buf: Vec::new(),
+            meta: trailer,
+            meta_body_buf: Vec::new(),
             creds,
             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> {
 impl<T: Write + Seek, C: Signer> Write for BlockStream<T, C> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.trailered.write(buf)
         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> {
 impl<T: Write + Seek, C: Signer> WriteInteg for BlockStream<T, C> {
     fn flush_integ(&mut self, integrity: &[u8]) -> io::Result<()> {
     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);
         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
             .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(())
         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> {
     fn block_key(&self) -> Result<SymKey> {
         let readcap = self
         let readcap = self
-            .trailer
-            .header
+            .meta
+            .body
             .readcaps
             .readcaps
             .get(&self.creds.principal())
             .get(&self.creds.principal())
             .ok_or(Error::Crypto(crypto::Error::NoReadCap))?;
             .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<()> {
     fn add_readcap_for(&mut self, owner: Principal, key: &dyn Encrypter) -> Result<()> {
         let block_key = self.block_key()?;
         let block_key = self.block_key()?;
         let readcap = key.ser_encrypt(&block_key)?;
         let readcap = key.ser_encrypt(&block_key)?;
-        self.trailer.header.readcaps.insert(owner, readcap);
+        self.meta.body.readcaps.insert(owner, readcap);
         Ok(())
         Ok(())
     }
     }
 
 
     fn integrity(&self) -> Option<&[u8]> {
     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) {
     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> {
     fn block_key(&self) -> Result<SymKey> {
         self.inner.block_key()
         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.
 /// An envelopment of a key, which is tagged with the principal who the key is meant for.
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
@@ -1217,7 +1207,7 @@ struct FragmentSerial(u32);
 
 
 #[cfg(test)]
 #[cfg(test)]
 mod tests {
 mod tests {
-    use std::io::Cursor;
+    use std::{fs::OpenOptions, io::Cursor};
 
 
     use crate::crypto::{tpm::TpmCredStore, CredStore, CredsPriv};
     use crate::crypto::{tpm::TpmCredStore, CredStore, CredsPriv};
 
 
@@ -1691,7 +1681,6 @@ mod tests {
     #[test]
     #[test]
     fn block_contents_persisted() {
     fn block_contents_persisted() {
         const EXPECTED: &[u8] = b"Silly sordid sulking sultans.";
         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 temp_dir = TempDir::new("btlib").expect("failed to create temp dir");
         let file_path = temp_dir.path().join("test.blk").to_owned();
         let file_path = temp_dir.path().join("test.blk").to_owned();
         let harness = SwtpmHarness::new().expect("failed to start swtpm");
         let harness = SwtpmHarness::new().expect("failed to start swtpm");
@@ -1699,7 +1688,7 @@ mod tests {
         let cred_store = TpmCredStore::new(context, harness.state_path())
         let cred_store = TpmCredStore::new(context, harness.state_path())
             .expect("failed to create TpmCredStore");
             .expect("failed to create TpmCredStore");
         let root_creds = cred_store
         let root_creds = cred_store
-            .gen_root_creds(PASSWORD)
+            .gen_root_creds("(1337Prestidigitation7331)")
             .expect("failed to get root creds");
             .expect("failed to get root creds");
         let mut node_creds = cred_store.node_creds().expect("failed to get node creds");
         let mut node_creds = cred_store.node_creds().expect("failed to get node creds");
         let writecap = root_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.
     // would be invalid.
     let (writecap, creds) = make_writecap_and_creds(vec!["apps"]);
     let (writecap, creds) = make_writecap_and_creds(vec!["apps"]);
     let root_writecap = writecap.next.as_ref().unwrap();
     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"]),
         path: make_path_with_root(root_writecap.issued_to.clone(), vec!["apps", "verse"]),
         readcaps,
         readcaps,
         writecap: Some(writecap),
         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 sig = Signature::copy_from(Sign::RSA_PSS_3072_SHA_256, &SIGNATURE);
     let mut stream =
     let mut stream =
         BlockStream::new(BtCursor::new(Vec::new()), creds).expect("create block stream failed");
         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 block_key = stream.block_key().expect("get block key failed");
     let stream = MerkleStream::new(stream).expect("create merkle stream failed");
     let stream = MerkleStream::new(stream).expect("create merkle stream failed");
     let stream = SecretStream::new(block_key)
     let stream = SecretStream::new(block_key)