Skip to content

Commit 97aa214

Browse files
committed
feat: verify protocol parameters chaining in certificate chain
1 parent 82be435 commit 97aa214

File tree

1 file changed

+58
-6
lines changed

1 file changed

+58
-6
lines changed

mithril-common/src/certificate_chain/certificate_verifier.rs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ pub enum CertificateVerifierError {
5353
#[error("certificate chain AVK unmatch error")]
5454
CertificateChainAVKUnmatch,
5555

56+
/// Error raised when validating the certificate chain if the current [Certificate]
57+
/// `protocol_parameters` don't match the signed `next_protocol_parameters` of the previous certificate
58+
/// (if the certificates are on different epoch) or the `protocol_parameters` of the previous certificate
59+
/// (if the certificates are on the same epoch).
60+
#[error("certificate chain protocol parameters unmatch error")]
61+
CertificateChainProtocolParametersUnmatch,
62+
5663
/// Error raised when validating the certificate chain if the current [Certificate]
5764
/// `epoch` doesn't match the signed `current_epoch` of the current certificate
5865
#[error("certificate epoch unmatch error")]
@@ -286,6 +293,40 @@ impl MithrilCertificateVerifier {
286293

287294
Ok(())
288295
}
296+
297+
fn verify_protocol_parameters_chaining(
298+
&self,
299+
certificate: &Certificate,
300+
previous_certificate: &Certificate,
301+
) -> StdResult<()> {
302+
let previous_certificate_has_same_epoch = previous_certificate.epoch == certificate.epoch;
303+
let certificate_has_valid_protocol_parameters = if previous_certificate_has_same_epoch {
304+
previous_certificate.metadata.protocol_parameters
305+
== certificate.metadata.protocol_parameters
306+
} else {
307+
match &previous_certificate
308+
.protocol_message
309+
.get_message_part(&ProtocolMessagePartKey::NextProtocolParameters)
310+
{
311+
Some(previous_certificate_next_protocol_parameters) => {
312+
**previous_certificate_next_protocol_parameters
313+
== certificate.metadata.protocol_parameters.compute_hash()
314+
}
315+
None => false,
316+
}
317+
};
318+
if !certificate_has_valid_protocol_parameters {
319+
debug!(
320+
self.logger,
321+
"Previous certificate {:#?}", previous_certificate
322+
);
323+
return Err(anyhow!(
324+
CertificateVerifierError::CertificateChainProtocolParametersUnmatch
325+
));
326+
}
327+
328+
Ok(())
329+
}
289330
}
290331

291332
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
@@ -338,6 +379,7 @@ impl CertificateVerifier for MithrilCertificateVerifier {
338379
previous_certificate,
339380
)?;
340381
self.verify_aggregate_verification_key_chaining(certificate, previous_certificate)?;
382+
self.verify_protocol_parameters_chaining(certificate, previous_certificate)?;
341383

342384
Ok(())
343385
}
@@ -846,22 +888,32 @@ mod tests {
846888
}
847889

848890
#[tokio::test]
849-
async fn verify_certificate_ko_certificate_hash_not_matching() {
891+
async fn verify_standard_certificate_fails_if_certificate_chain_protocol_parameters_unmatch() {
850892
let (total_certificates, certificates_per_epoch) = (5, 1);
851893
let (fake_certificates, _) =
852894
setup_certificate_chain(total_certificates, certificates_per_epoch);
895+
let verifier = MockDependencyInjector::new().build_certificate_verifier();
853896
let mut certificate = fake_certificates[0].clone();
854-
certificate.hash = "another-hash".to_string();
855-
let previous_certificate = fake_certificates[1].clone();
856-
let mock_container = MockDependencyInjector::new();
857-
let verifier = mock_container.build_certificate_verifier();
897+
let mut previous_certificate = fake_certificates[1].clone();
898+
previous_certificate.protocol_message.set_message_part(
899+
ProtocolMessagePartKey::NextProtocolParameters,
900+
"protocol-params-hash-123".to_string(),
901+
);
902+
previous_certificate.hash = previous_certificate.compute_hash();
903+
certificate
904+
.previous_hash
905+
.clone_from(&previous_certificate.hash);
906+
certificate.hash = certificate.compute_hash();
858907

859908
let error = verifier
860909
.verify_standard_certificate(&certificate, &previous_certificate)
861910
.await
862911
.expect_err("verify_standard_certificate should fail");
863912

864-
assert_error_matches!(CertificateVerifierError::CertificateHashUnmatch, error)
913+
assert_error_matches!(
914+
CertificateVerifierError::CertificateChainProtocolParametersUnmatch,
915+
error
916+
)
865917
}
866918

867919
#[tokio::test]

0 commit comments

Comments
 (0)