Skip to content

Commit 7667ec0

Browse files
src: split up different uses of SHA-256
src/fsverity.rs defines Sha256HashValue as an implementation of FsVerityHashValue but we also use it for situations where we handle SHA-256 digests that aren't fs-verity hash values. This happens a lot in the OCI code (to refer to images and layers) and correspondingly in the splitstream code (which stores those things). Introduce a util::Sha256Digest type, returned by util::parse_sha256() and use it consistently for all of the cases that have nothing to do with fs-verity. parse_sha256() is still used in some places in the code for values that are intended as fs-verity digests. We'll start fixing that up in the following commits when we add some helpers directly on the types themselves. Signed-off-by: Allison Karlitskaya <[email protected]>
1 parent 49ba9dd commit 7667ec0

File tree

4 files changed

+28
-27
lines changed

4 files changed

+28
-27
lines changed

src/oci/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ use crate::{
1919
oci::tar::{get_entry, split_async},
2020
repository::Repository,
2121
splitstream::DigestMap,
22-
util::parse_sha256,
22+
util::{parse_sha256, Sha256Digest},
2323
};
2424

2525
pub fn import_layer(
2626
repo: &Repository,
27-
sha256: &Sha256HashValue,
27+
sha256: &Sha256Digest,
2828
name: Option<&str>,
2929
tar_stream: &mut impl Read,
3030
) -> Result<Sha256HashValue> {
@@ -48,21 +48,21 @@ struct ImageOp<'repo> {
4848
progress: MultiProgress,
4949
}
5050

51-
fn sha256_from_descriptor(descriptor: &Descriptor) -> Result<Sha256HashValue> {
51+
fn sha256_from_descriptor(descriptor: &Descriptor) -> Result<Sha256Digest> {
5252
let Some(digest) = descriptor.as_digest_sha256() else {
5353
bail!("Descriptor in oci config is not sha256");
5454
};
5555
Ok(parse_sha256(digest)?)
5656
}
5757

58-
fn sha256_from_digest(digest: &str) -> Result<Sha256HashValue> {
58+
fn sha256_from_digest(digest: &str) -> Result<Sha256Digest> {
5959
match digest.strip_prefix("sha256:") {
6060
Some(rest) => Ok(parse_sha256(rest)?),
6161
None => bail!("Manifest has non-sha256 digest"),
6262
}
6363
}
6464

65-
type ContentAndVerity = (Sha256HashValue, Sha256HashValue);
65+
type ContentAndVerity = (Sha256Digest, Sha256HashValue);
6666

6767
impl<'repo> ImageOp<'repo> {
6868
async fn new(repo: &'repo Repository, imgref: &str) -> Result<Self> {
@@ -93,7 +93,7 @@ impl<'repo> ImageOp<'repo> {
9393

9494
pub async fn ensure_layer(
9595
&self,
96-
layer_sha256: &Sha256HashValue,
96+
layer_sha256: &Sha256Digest,
9797
descriptor: &Descriptor,
9898
) -> Result<Sha256HashValue> {
9999
// We need to use the per_manifest descriptor to download the compressed layer but it gets
@@ -245,7 +245,7 @@ pub fn open_config(
245245
Ok((config, stream.refs))
246246
}
247247

248-
fn hash(bytes: &[u8]) -> Sha256HashValue {
248+
fn hash(bytes: &[u8]) -> Sha256Digest {
249249
let mut context = Sha256::new();
250250
context.update(bytes);
251251
context.finalize().into()

src/repository.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
},
2525
mount::mount_composefs_at,
2626
splitstream::{DigestMap, SplitStreamReader, SplitStreamWriter},
27-
util::{parse_sha256, proc_self_fd},
27+
util::{parse_sha256, proc_self_fd, Sha256Digest},
2828
};
2929

3030
#[derive(Debug)]
@@ -136,7 +136,7 @@ impl Repository {
136136
/// store the result.
137137
pub fn create_stream(
138138
&self,
139-
sha256: Option<Sha256HashValue>,
139+
sha256: Option<Sha256Digest>,
140140
maps: Option<DigestMap>,
141141
) -> SplitStreamWriter {
142142
SplitStreamWriter::new(self, maps, sha256)
@@ -166,7 +166,7 @@ impl Repository {
166166
format!("objects/{:02x}/{}", id[0], hex::encode(&id[1..]))
167167
}
168168

169-
pub fn has_stream(&self, sha256: &Sha256HashValue) -> Result<Option<Sha256HashValue>> {
169+
pub fn has_stream(&self, sha256: &Sha256Digest) -> Result<Option<Sha256HashValue>> {
170170
let stream_path = format!("streams/{}", hex::encode(sha256));
171171

172172
match readlinkat(&self.repository, &stream_path, []) {
@@ -191,7 +191,7 @@ impl Repository {
191191
}
192192

193193
/// Basically the same as has_stream() except that it performs expensive verification
194-
pub fn check_stream(&self, sha256: &Sha256HashValue) -> Result<Option<Sha256HashValue>> {
194+
pub fn check_stream(&self, sha256: &Sha256Digest) -> Result<Option<Sha256HashValue>> {
195195
match self.openat(&format!("streams/{}", hex::encode(sha256)), OFlags::RDONLY) {
196196
Ok(stream) => {
197197
let measured_verity: Sha256HashValue = measure_verity(&stream)?;
@@ -245,7 +245,7 @@ impl Repository {
245245

246246
/// Assign the given name to a stream. The stream must already exist. After this operation it
247247
/// will be possible to refer to the stream by its new name 'refs/{name}'.
248-
pub fn name_stream(&self, sha256: Sha256HashValue, name: &str) -> Result<()> {
248+
pub fn name_stream(&self, sha256: Sha256Digest, name: &str) -> Result<()> {
249249
let stream_path = format!("streams/{}", hex::encode(sha256));
250250
let reference_path = format!("streams/refs/{name}");
251251
self.symlink(&reference_path, &stream_path)?;
@@ -268,7 +268,7 @@ impl Repository {
268268
/// ID will be used when referring to the stream from other linked streams.
269269
pub fn ensure_stream(
270270
&self,
271-
sha256: &Sha256HashValue,
271+
sha256: &Sha256Digest,
272272
callback: impl FnOnce(&mut SplitStreamWriter) -> Result<()>,
273273
reference: Option<&str>,
274274
) -> Result<Sha256HashValue> {

src/splitstream.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use zstd::stream::{read::Decoder, write::Encoder};
1212
use crate::{
1313
fsverity::{FsVerityHashValue, Sha256HashValue},
1414
repository::Repository,
15-
util::read_exactish,
15+
util::{read_exactish, Sha256Digest},
1616
};
1717

1818
#[derive(Debug)]
1919
pub struct DigestMapEntry {
20-
pub body: Sha256HashValue,
20+
pub body: Sha256Digest,
2121
pub verity: Sha256HashValue,
2222
}
2323

@@ -37,14 +37,14 @@ impl DigestMap {
3737
DigestMap { map: vec![] }
3838
}
3939

40-
pub fn lookup(&self, body: &Sha256HashValue) -> Option<&Sha256HashValue> {
40+
pub fn lookup(&self, body: &Sha256Digest) -> Option<&Sha256HashValue> {
4141
match self.map.binary_search_by_key(body, |e| e.body) {
4242
Ok(idx) => Some(&self.map[idx].verity),
4343
Err(..) => None,
4444
}
4545
}
4646

47-
pub fn insert(&mut self, body: &Sha256HashValue, verity: &Sha256HashValue) {
47+
pub fn insert(&mut self, body: &Sha256Digest, verity: &Sha256HashValue) {
4848
match self.map.binary_search_by_key(body, |e| e.body) {
4949
Ok(idx) => assert_eq!(self.map[idx].verity, *verity), // or else, bad things...
5050
Err(idx) => self.map.insert(
@@ -62,7 +62,7 @@ pub struct SplitStreamWriter<'a> {
6262
repo: &'a Repository,
6363
inline_content: Vec<u8>,
6464
writer: Encoder<'a, Vec<u8>>,
65-
pub sha256: Option<(Sha256, Sha256HashValue)>,
65+
pub sha256: Option<(Sha256, Sha256Digest)>,
6666
}
6767

6868
impl std::fmt::Debug for SplitStreamWriter<'_> {
@@ -80,7 +80,7 @@ impl SplitStreamWriter<'_> {
8080
pub fn new(
8181
repo: &Repository,
8282
refs: Option<DigestMap>,
83-
sha256: Option<Sha256HashValue>,
83+
sha256: Option<Sha256Digest>,
8484
) -> SplitStreamWriter {
8585
// SAFETY: we surely can't get an error writing the header to a Vec<u8>
8686
let mut writer = Encoder::new(vec![], 0).unwrap();
@@ -157,7 +157,7 @@ impl SplitStreamWriter<'_> {
157157
self.flush_inline(vec![])?;
158158

159159
if let Some((context, expected)) = self.sha256 {
160-
if Into::<Sha256HashValue>::into(context.finalize()) != expected {
160+
if Into::<Sha256Digest>::into(context.finalize()) != expected {
161161
bail!("Content doesn't have expected SHA256 hash value!");
162162
}
163163
}
@@ -362,13 +362,13 @@ impl<R: Read> SplitStreamReader<R> {
362362
}
363363
}
364364

365-
pub fn get_stream_refs(&mut self, mut callback: impl FnMut(&Sha256HashValue)) {
365+
pub fn get_stream_refs(&mut self, mut callback: impl FnMut(&Sha256Digest)) {
366366
for entry in &self.refs.map {
367367
callback(&entry.body);
368368
}
369369
}
370370

371-
pub fn lookup(&self, body: &Sha256HashValue) -> Result<&Sha256HashValue> {
371+
pub fn lookup(&self, body: &Sha256Digest) -> Result<&Sha256HashValue> {
372372
match self.refs.lookup(body) {
373373
Some(id) => Ok(id),
374374
None => bail!("Reference is not found in splitstream"),

src/util.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ use std::{
55

66
use tokio::io::{AsyncRead, AsyncReadExt};
77

8-
use crate::fsverity::{FsVerityHashValue, Sha256HashValue};
9-
108
/// Formats a string like "/proc/self/fd/3" for the given fd. This can be used to work with kernel
119
/// APIs that don't directly accept file descriptors.
1210
///
@@ -83,14 +81,17 @@ pub(crate) async fn read_exactish_async(
8381
Ok(true)
8482
}
8583

86-
/// Parse a string containing a SHA256 digest in hexidecimal form into a Sha256HashValue.
84+
/// A utility type representing a SHA-256 digest in binary.
85+
pub type Sha256Digest = [u8; 32];
86+
87+
/// Parse a string containing a SHA256 digest in hexidecimal form into a Sha256Digest.
8788
///
8889
/// The string must contain exactly 64 characters and consist entirely of [0-9a-f], case
8990
/// insensitive.
9091
///
9192
/// In case of a failure to parse the string, this function returns ErrorKind::InvalidInput.
92-
pub fn parse_sha256(string: impl AsRef<str>) -> Result<Sha256HashValue> {
93-
let mut value = Sha256HashValue::EMPTY;
93+
pub fn parse_sha256(string: impl AsRef<str>) -> Result<Sha256Digest> {
94+
let mut value = [0u8; 32];
9495
hex::decode_to_slice(string.as_ref(), &mut value)
9596
.map_err(|source| Error::new(ErrorKind::InvalidInput, source))?;
9697
Ok(value)

0 commit comments

Comments
 (0)