Skip to content

Commit 3d9faf8

Browse files
Improve role 0 signing key validation
1 parent 06536b8 commit 3d9faf8

File tree

2 files changed

+65
-9
lines changed

2 files changed

+65
-9
lines changed

rust/rbac-registration/src/cardano/cip509/cip509.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl Cip509 {
172172
// The following checks are only performed for the role 0.
173173
if let Some(role_data) = cip509.role_data(RoleNumber::ROLE_0) {
174174
validate_stake_public_key(txn, cip509.certificate_uris(), &cip509.report);
175-
validate_role_signing_key(role_data, &cip509.report);
175+
validate_role_signing_key(role_data, cip509.metadata.as_ref(), &cip509.report);
176176
}
177177

178178
Ok(Some(cip509))

rust/rbac-registration/src/cardano/cip509/validation.rs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ use pallas::{
3737
};
3838

3939
use super::utils::cip19::compare_key_hash;
40-
use crate::cardano::cip509::{types::TxInputHash, Cip0134UriSet, LocalRefInt, RoleData};
40+
use crate::cardano::cip509::{
41+
rbac::Cip509RbacMetadata, types::TxInputHash, Cip0134UriSet, KeyLocalRef, LocalRefInt, RoleData,
42+
};
4143

4244
/// Context-specific primitive type with tag number 6 (`raw_tag` 134) for
4345
/// uniform resource identifier (URI) in the subject alternative name extension.
@@ -174,17 +176,71 @@ fn extract_stake_addresses(uris: Option<&Cip0134UriSet>) -> Vec<VKeyHash> {
174176

175177
/// Validate role singing key for role 0.
176178
/// Must reference certificate not the public key
177-
pub fn validate_role_signing_key(role_data: &RoleData, report: &ProblemReport) {
178-
let Some(role_signing_key) = role_data.signing_key() else {
179+
pub fn validate_role_signing_key(
180+
role_data: &RoleData, metadata: Option<&Cip509RbacMetadata>, report: &ProblemReport,
181+
) {
182+
let context = "Cip509 role0 signing key validation";
183+
184+
let Some(signing_key) = role_data.signing_key() else {
185+
report.missing_field("RoleData::signing_key", context);
186+
return;
187+
};
188+
189+
let Some(metadata) = metadata else {
190+
report.other("Missing metadata", context);
191+
return;
192+
};
193+
194+
match signing_key.local_ref {
195+
LocalRefInt::X509Certs => {
196+
check_key_offset(
197+
signing_key,
198+
metadata.x509_certs.as_slice(),
199+
"X509",
200+
context,
201+
report,
202+
);
203+
},
204+
LocalRefInt::C509Certs => {
205+
check_key_offset(
206+
signing_key,
207+
metadata.c509_certs.as_slice(),
208+
"C509",
209+
context,
210+
report,
211+
);
212+
},
213+
LocalRefInt::PubKeys => {
214+
report.invalid_value(
215+
"RoleData::signing_key",
216+
&format!("{signing_key:?}"),
217+
"Role signing key should reference certificate, not public key",
218+
context,
219+
);
220+
},
221+
}
222+
}
223+
224+
fn check_key_offset<T>(
225+
key: &KeyLocalRef, certificates: &[T], certificate_type: &str, context: &str,
226+
report: &ProblemReport,
227+
) {
228+
let Ok(offset) = usize::try_from(key.key_offset) else {
229+
report.invalid_value(
230+
"RoleData::signing_key",
231+
&format!("{key:?}"),
232+
"Role signing key offset is too big",
233+
context,
234+
);
179235
return;
180236
};
181237

182-
if role_signing_key.local_ref == LocalRefInt::PubKeys {
238+
if offset >= certificates.len() {
183239
report.invalid_value(
184-
"RoleData::role_signing_key",
185-
&format!("{role_signing_key:?}"),
186-
"Role signing key should reference certificate, not public key",
187-
"Cip509 role0 signing key validation",
240+
"RoleData::signing_key",
241+
&format!("{key:?}"),
242+
&format!("Role signing key should reference existing certificate, but there are only {} {} certificates in this registration", certificates.len(), certificate_type),
243+
context,
188244
);
189245
}
190246
}

0 commit comments

Comments
 (0)