diff --git a/src/ffi/presentation.rs b/src/ffi/presentation.rs index b1b89bba..bfb542d0 100644 --- a/src/ffi/presentation.rs +++ b/src/ffi/presentation.rs @@ -195,6 +195,47 @@ pub extern "C" fn anoncreds_create_presentation( }) } +/// Optional value for overriding the non-revoked interval in the PresentationRequest +/// This only overrides the `from` value as a Revocation Status List is deemed valid until the next +/// entry. +/// +/// E.g. if the ledger has Revocation Status List at timestamps [0, 100, 200], +/// let's call them List0, List100, List200. Then: +/// +/// List0 is valid List100 is valid +/// ______|_______ _______|_______ +/// | | | +/// List 0 ----------- 100 ----------- 200 +/// +/// A `nonrevoked_interval = {from: 50, to: 150}` should accept both List0 and +/// List100. +/// +#[derive(Debug)] +#[repr(C)] +pub struct FfiNonrevokedIntervalOverride<'a> { + rev_reg_def_id: FfiStr<'a>, + /// Timestamp in the `PresentationRequest` + req_timestamp: i64, + /// Timestamp from which verifier accepts, + /// should be less than `req_timestamp` + override_timestamp: i64, +} + +impl<'a> FfiNonrevokedIntervalOverride<'a> { + fn load(&self) -> Result<(RevocationRegistryDefinitionId, u64, u64)> { + let id = RevocationRegistryDefinitionId::new(self.rev_reg_def_id.as_str().to_owned())?; + let req_timestamp = self + .req_timestamp + .try_into() + .map_err(|_| err_msg!("Invalid req timestamp "))?; + let override_timestamp = self + .override_timestamp + .try_into() + .map_err(|_| err_msg!("Invalid override timestamp "))?; + Ok((id, req_timestamp, override_timestamp)) + } +} + #[no_mangle] pub extern "C" fn anoncreds_verify_presentation( presentation: ObjectHandle, @@ -206,6 +247,7 @@ pub extern "C" fn anoncreds_verify_presentation( rev_reg_defs: FfiList, rev_reg_def_ids: FfiStrList, rev_status_list: FfiList, + nonrevoked_interval_override: FfiList, result_p: *mut i8, ) -> ErrorCode { catch_error(|| { @@ -266,6 +308,24 @@ pub extern "C" fn anoncreds_verify_presentation( let rev_status_list: Result> = rev_status_list.refs(); let rev_status_list = rev_status_list.ok(); + let override_entries = { + let override_ffi_entries = nonrevoked_interval_override.as_slice(); + override_ffi_entries.into_iter().try_fold( + Vec::with_capacity(override_ffi_entries.len()), + |mut v, entry| -> Result> { + v.push(entry.load()?); + Ok(v) + }, + )? + }; + let mut map_nonrevoked_interval_override = HashMap::new(); + for (id, req_timestamp, override_timestamp) in override_entries.iter() { + map_nonrevoked_interval_override + .entry(id) + .or_insert_with(HashMap::new) + .insert(*req_timestamp, *override_timestamp); + } + let verify = verify_presentation( presentation.load()?.cast_ref()?, pres_req.load()?.cast_ref()?, @@ -273,6 +333,7 @@ pub extern "C" fn anoncreds_verify_presentation( &cred_defs, rev_reg_defs, rev_status_list, + Some(&map_nonrevoked_interval_override), )?; unsafe { *result_p = verify as i8 }; Ok(()) diff --git a/src/services/verifier.rs b/src/services/verifier.rs index 707d7cf2..d3b92730 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -44,6 +44,9 @@ pub fn verify_presentation( cred_defs: &HashMap<&CredentialDefinitionId, &CredentialDefinition>, rev_reg_defs: Option<&HashMap<&RevocationRegistryDefinitionId, &RevocationRegistryDefinition>>, rev_status_lists: Option>, + nonrevoke_interval_override: Option< + &HashMap<&RevocationRegistryDefinitionId, HashMap>, + >, ) -> Result { trace!("verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists);