Fix cross-vault OCSP snapshot poisoning
This commit is contained in:
1 parent
69d78939a1
commit
dab4b9e0bb
9 files changed
+172
-23
No files matched your search
@@ -38,6 +38,8 @@ struct RawSnapshot {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RawIssuer {
|
||||
#[serde(default)]
|
||||
id: String,
|
||||
#[serde(default)]
|
||||
sha256: String,
|
||||
}
|
||||
@@ -53,12 +55,22 @@ struct RawEntry {
|
||||
}
|
||||
|
||||
impl Snapshot {
|
||||
/// Parse and validate a snapshot against the configured CA fingerprint.
|
||||
pub fn parse(bytes: &[u8], expected_sha256: &str) -> Result<Self, SnapshotError> {
|
||||
/// Parse and validate a snapshot against the configured CA identity.
|
||||
pub fn parse(
|
||||
bytes: &[u8],
|
||||
expected_sha256: &str,
|
||||
expected_ca_id: &str,
|
||||
) -> Result<Self, SnapshotError> {
|
||||
let raw: RawSnapshot = serde_json::from_slice(bytes)?;
|
||||
if raw.schema != SCHEMA {
|
||||
return Err(SnapshotError::Schema(raw.schema));
|
||||
}
|
||||
if !raw.issuer.id.eq_ignore_ascii_case(expected_ca_id) {
|
||||
return Err(SnapshotError::IssuerIdMismatch {
|
||||
expected: expected_ca_id.to_string(),
|
||||
actual: raw.issuer.id,
|
||||
});
|
||||
}
|
||||
if !raw.issuer.sha256.eq_ignore_ascii_case(expected_sha256) {
|
||||
return Err(SnapshotError::IssuerMismatch {
|
||||
expected: expected_sha256.to_string(),
|
||||
@@ -158,6 +170,8 @@ pub enum SnapshotError {
|
||||
Json(#[from] serde_json::Error),
|
||||
#[error("unsupported snapshot schema {0:?}")]
|
||||
Schema(String),
|
||||
#[error("snapshot issuer ID {actual} does not match configured CA ID {expected}")]
|
||||
IssuerIdMismatch { expected: String, actual: String },
|
||||
#[error("snapshot issuer {actual} does not match configured CA {expected}")]
|
||||
IssuerMismatch { expected: String, actual: String },
|
||||
#[error("invalid serial {0:?}")]
|
||||
@@ -191,7 +205,7 @@ mod tests {
|
||||
#[test]
|
||||
fn parses_statuses_and_reasons() {
|
||||
let sha = sha256_hex(b"ca");
|
||||
let snapshot = Snapshot::parse(body(&sha).as_bytes(), &sha).unwrap();
|
||||
let snapshot = Snapshot::parse(body(&sha).as_bytes(), &sha, "ca").unwrap();
|
||||
let good = snapshot.status_for_serial(&[0x01, 0xab]).unwrap();
|
||||
assert_eq!(good.status, Status::Good);
|
||||
let revoked = snapshot.status_for_serial(&[0xff]).unwrap();
|
||||
@@ -203,11 +217,15 @@ mod tests {
|
||||
#[test]
|
||||
fn rejects_wrong_issuer_schema_and_duplicates() {
|
||||
let sha = sha256_hex(b"ca");
|
||||
assert!(Snapshot::parse(body(&sha).as_bytes(), "wrong").is_err());
|
||||
assert!(Snapshot::parse(body(&sha).as_bytes(), "wrong", "ca").is_err());
|
||||
assert!(matches!(
|
||||
Snapshot::parse(body(&sha).as_bytes(), &sha, "other"),
|
||||
Err(SnapshotError::IssuerIdMismatch { .. })
|
||||
));
|
||||
let wrong_schema = body(&sha).replace(SCHEMA, "other");
|
||||
assert!(Snapshot::parse(wrong_schema.as_bytes(), &sha).is_err());
|
||||
assert!(Snapshot::parse(wrong_schema.as_bytes(), &sha, "ca").is_err());
|
||||
let duplicate = body(&sha).replace("\"00ff\"", "\"01ab\"");
|
||||
assert!(Snapshot::parse(duplicate.as_bytes(), &sha).is_err());
|
||||
assert!(Snapshot::parse(duplicate.as_bytes(), &sha, "ca").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user