fix(nix-compat/narinfo): don't panic trying to parse signatures

BASE64.decode_mut panics if we're passing data that has the wrong size.
Do the size check first and error out there.

Also update the error, and talk about b64-encoded sizes.

Change-Id: I290f80a37d48526a30bf1df9d1d9fe34865008eb
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10146
Tested-by: BuildkiteCI
Reviewed-by: edef <edef@edef.eu>
Autosubmit: flokli <flokli@flokli.de>
This commit is contained in:
Florian Klink 2023-11-27 16:36:19 +02:00 committed by clbot
parent dfaaf41cef
commit b7de931cc6

View file

@ -20,13 +20,15 @@ impl<'a> Signature<'a> {
.split_once(':')
.ok_or(SignatureError::MissingSeparator)?;
let mut buf = [0; SIGNATURE_LENGTH + 2];
if bytes64.len() != BASE64.encode_len(SIGNATURE_LENGTH) {
return Err(SignatureError::InvalidSignatureLen(bytes64.len()));
}
let mut bytes = [0; SIGNATURE_LENGTH];
let mut buf = [0; SIGNATURE_LENGTH + 2];
match BASE64.decode_mut(bytes64.as_bytes(), &mut buf) {
Ok(SIGNATURE_LENGTH) => {
bytes.copy_from_slice(&buf[..SIGNATURE_LENGTH]);
}
Ok(n) => return Err(SignatureError::InvalidSignatureLen(n)),
Ok(SIGNATURE_LENGTH) => bytes.copy_from_slice(&buf[..SIGNATURE_LENGTH]),
Ok(_) => unreachable!(),
// keeping DecodePartial gets annoying lifetime-wise
Err(_) => return Err(SignatureError::DecodeError(input.to_string())),
}
@ -54,7 +56,7 @@ impl<'a> Signature<'a> {
pub enum SignatureError {
#[error("Missing separator")]
MissingSeparator,
#[error("Invalid signature len: {0}")]
#[error("Invalid signature len: (expected {} b64-encoded, got {}", BASE64.encode_len(SIGNATURE_LENGTH), .0)]
InvalidSignatureLen(usize),
#[error("Unable to base64-decode signature: {0}")]
DecodeError(String),
@ -111,4 +113,9 @@ mod test {
let sig = Signature::parse(sig_str).expect("must parse");
assert_eq!(expect_valid, sig.verify(fp.as_bytes(), verifying_key));
}
#[test_case("cache.nixos.org-1:o1DTsjCz0PofLJ216P2RBuSulI8BAb6zHxWE4N+tzlcELk5Uk/GO2SCxWTRN5wJutLZZ+cHTMdWqOHF8"; "wrong_length")]
fn parse_fail(input: &'static str) {
Signature::parse(input).expect_err("must fail");
}
}