@@ -37,7 +37,9 @@ use pallas::{
3737} ;
3838
3939use 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