summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-05-16 17:11:26 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-05-16 17:11:26 +0200
commitba036bfb1f4c6def2f916b9ef135ec7b5a98fcdb (patch)
tree0c40bf4d07a500c100c20313d9125aac2efb5cb9
parentc05e6e2dbd4f0e22a1b74c3e9ef8f05b4479aad8 (diff)
openpgp: Introduce trait Policy. WIPfix-274
- Add a new trait `sequoia_openpgp::Policy`. Currently, this trait only has one method that returns the current time. This time is used when evaluating signatures. - Use this trait in TPK::{revocation_status,alive,expired}. Remove the corresponding *_at() functions. - Fixes #274.
-rw-r--r--openpgp-ffi/src/tpk.rs19
-rw-r--r--openpgp/src/lib.rs46
-rw-r--r--openpgp/src/tpk/builder.rs4
-rw-r--r--openpgp/src/tpk/mod.rs79
-rw-r--r--sqv/src/sqv.rs4
-rw-r--r--tool/src/commands/inspect.rs2
6 files changed, 94 insertions, 60 deletions
diff --git a/openpgp-ffi/src/tpk.rs b/openpgp-ffi/src/tpk.rs
index 259b3a1c..c7ddc1c3 100644
--- a/openpgp-ffi/src/tpk.rs
+++ b/openpgp-ffi/src/tpk.rs
@@ -11,6 +11,7 @@ use libc::{c_char, c_int, size_t, time_t, uint8_t};
extern crate sequoia_openpgp as openpgp;
use self::openpgp::{
+ Policy,
autocrypt::Autocrypt,
crypto,
constants::ReasonForRevocation,
@@ -162,12 +163,12 @@ fn pgp_tpk_revocation_status_at(tpk: *const TPK, when: time_t)
{
let when = when as i64;
let when = if when == 0 {
- None
+ time::now()
} else {
- Some(time::at(time::Timespec::new(when, 0)))
+ time::at(time::Timespec::new(when, 0))
};
- tpk.ref_raw().revocation_status_at(when).move_into_raw()
+ tpk.ref_raw().revocation_status(&when as &Policy).move_into_raw()
}
/// Returns the TPK's current revocation status.
@@ -179,7 +180,7 @@ fn pgp_tpk_revocation_status_at(tpk: *const TPK, when: time_t)
fn pgp_tpk_revocation_status(tpk: *const TPK)
-> *mut RevocationStatus<'static>
{
- tpk.ref_raw().revocation_status().move_into_raw()
+ tpk.ref_raw().revocation_status(None).move_into_raw()
}
fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation {
@@ -330,7 +331,7 @@ fn pgp_tpk_expired(tpk: *const TPK)
-> c_int {
let tpk = tpk.ref_raw();
- tpk.expired() as c_int
+ tpk.expired(None) as c_int
}
/// Returns whether the TPK has expired.
@@ -338,7 +339,8 @@ fn pgp_tpk_expired(tpk: *const TPK)
fn pgp_tpk_expired_at(tpk: *const TPK, when: time_t)
-> c_int {
let tpk = tpk.ref_raw();
- tpk.expired_at(time::at(time::Timespec::new(when as i64, 0))) as c_int
+ tpk.expired(&time::at(time::Timespec::new(when as i64, 0)) as &Policy)
+ as c_int
}
/// Returns whether the TPK is alive.
@@ -347,7 +349,7 @@ fn pgp_tpk_alive(tpk: *const TPK)
-> c_int {
let tpk = tpk.ref_raw();
- tpk.alive() as c_int
+ tpk.alive(None) as c_int
}
/// Returns whether the TPK is alive at the specified time.
@@ -355,7 +357,8 @@ fn pgp_tpk_alive(tpk: *const TPK)
fn pgp_tpk_alive_at(tpk: *const TPK, when: time_t)
-> c_int {
let tpk = tpk.ref_raw();
- tpk.alive_at(time::at(time::Timespec::new(when as i64, 0))) as c_int
+ tpk.alive(&time::at(time::Timespec::new(when as i64, 0)) as &Policy)
+ as c_int
}
/// Changes the TPK's expiration.
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index c9fe4ff5..20515cba 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -515,3 +515,49 @@ pub enum RevocationStatus<'a> {
/// revocation certificate.
NotAsFarAsWeKnow,
}
+
+/// A policy for cryptographic operations.
+///
+/// # Example
+///
+/// This demonstrates how to evaluate signatures for a different time.
+///
+/// ```rust
+/// # extern crate time;
+/// # use sequoia_openpgp::*;
+/// # fn f(tpk: &TPK) -> Result<()> {
+/// // First option: Explicit implementation of Policy:
+/// struct NextWeek(());
+///
+/// impl Policy for NextWeek {
+/// fn current_time(&self) -> time::Tm {
+/// time::now() + time::Duration::weeks(1)
+/// }
+/// }
+///
+/// let alive = tpk.alive(&NextWeek(()) as &Policy);
+///
+/// // Second option: Use time::Tm as Policy:
+/// let next_week = time::now() + time::Duration::weeks(1);
+/// let alive_ = tpk.alive(&next_week as &Policy);
+///
+/// assert_eq!(alive, alive_);
+/// # Ok(()) }
+/// ```
+pub trait Policy {
+ /// Returns the time relative to which signatures are evaluated.
+ ///
+ /// The default implementation returns the current time.
+ fn current_time(&self) -> time::Tm {
+ time::now()
+ }
+}
+
+struct DefaultPolicy(());
+impl Policy for DefaultPolicy {}
+
+impl Policy for time::Tm {
+ fn current_time(&self) -> time::Tm {
+ self.clone()
+ }
+}
diff --git a/openpgp/src/tpk/builder.rs b/openpgp/src/tpk/builder.rs
index e6c8ba2b..8bf3ceb8 100644
--- a/openpgp/src/tpk/builder.rs
+++ b/openpgp/src/tpk/builder.rs
@@ -555,11 +555,11 @@ mod tests {
let (tpk, revocation) = TPKBuilder::new()
.set_cipher_suite(CipherSuite::Cv25519)
.generate().unwrap();
- assert_eq!(tpk.revocation_status(),
+ assert_eq!(tpk.revocation_status(None),
RevocationStatus::NotAsFarAsWeKnow);
let tpk = tpk.merge_packets(vec![revocation.clone().into()]).unwrap();
- assert_eq!(tpk.revocation_status(),
+ assert_eq!(tpk.revocation_status(None),
RevocationStatus::Revoked(&[revocation]));
}
diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs
index 011a312c..6fd113ef 100644
--- a/openpgp/src/tpk/mod.rs
+++ b/openpgp/src/tpk/mod.rs
@@ -31,6 +31,8 @@ use {
TPK,
KeyID,
Fingerprint,
+ Policy,
+ DefaultPolicy,
};
use parse::{Parse, PacketParserResult, PacketParser};
use serialize::SerializeInto;
@@ -871,7 +873,7 @@ impl<'a> Iterator for KeyIter<'a> {
self.primary = true;
(tpk.primary_key_signature(),
- tpk.revocation_status(),
+ tpk.revocation_status(None),
tpk.primary())
} else {
self.subkey_iter.next()
@@ -1705,10 +1707,11 @@ impl TPK {
/// Note: this only returns whether the primary key is revoked. If you
/// want to know whether a subkey, user id, etc., is revoked, then
/// you need to query them separately.
- pub fn revocation_status_at<T>(&self, t: T) -> RevocationStatus
- where T: Into<Option<time::Tm>>
+ pub fn revocation_status<'a, P>(&self, policy: P) -> RevocationStatus
+ where P: Into<Option<&'a dyn Policy>>
{
- let t = t.into().unwrap_or_else(time::now_utc);
+ let p = policy.into().unwrap_or(&DefaultPolicy(()));
+ let t = p.current_time();
let has_self_revs =
active_revocation(&self.primary_selfsigs,
&self.primary_self_revocations, t);
@@ -1728,15 +1731,6 @@ impl TPK {
}
}
- /// Returns the TPK's current revocation status.
- ///
- /// Note: this only returns whether the primary key is revoked. If you
- /// want to know whether a subkey, user id, etc., is revoked, then
- /// you need to query them separately.
- pub fn revocation_status(&self) -> RevocationStatus {
- self.revocation_status_at(None)
- }
-
/// Returns a revocation certificate for the TPK.
///
/// # Example
@@ -1756,7 +1750,7 @@ impl TPK {
/// .set_cipher_suite(CipherSuite::Cv25519)
/// .generate()?;
/// assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
- /// tpk.revocation_status());
+ /// tpk.revocation_status(None));
///
/// let mut keypair = tpk.primary().clone().into_keypair()?;
/// let sig = tpk.revoke(&mut keypair, ReasonForRevocation::KeyCompromised,
@@ -1765,7 +1759,7 @@ impl TPK {
///
/// let tpk = tpk.merge_packets(vec![sig.clone().into()])?;
/// assert_eq!(RevocationStatus::Revoked(&[sig]),
- /// tpk.revocation_status());
+ /// tpk.revocation_status(None));
/// # Ok(())
/// # }
pub fn revoke(&self, primary_signer: &mut Signer,
@@ -1810,13 +1804,13 @@ impl TPK {
/// .set_cipher_suite(CipherSuite::Cv25519)
/// .generate()?;
/// assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
- /// tpk.revocation_status());
+ /// tpk.revocation_status(None));
///
/// let mut keypair = tpk.primary().clone().into_keypair()?;
/// let tpk = tpk.revoke_in_place(&mut keypair,
/// ReasonForRevocation::KeyCompromised,
/// b"It was the maid :/")?;
- /// if let RevocationStatus::Revoked(sigs) = tpk.revocation_status() {
+ /// if let RevocationStatus::Revoked(sigs) = tpk.revocation_status(None) {
/// assert_eq!(sigs.len(), 1);
/// assert_eq!(sigs[0].sigtype(), SignatureType::KeyRevocation);
/// assert_eq!(sigs[0].reason_for_revocation(),
@@ -1837,36 +1831,24 @@ impl TPK {
}
/// Returns whether or not the TPK has expired.
- pub fn expired(&self) -> bool {
- if let Some(Signature::V4(sig)) = self.primary_key_signature() {
- sig.key_expired(self.primary())
- } else {
- false
- }
- }
-
- /// Returns whether or not the key is expired at the given time.
- pub fn expired_at(&self, tm: time::Tm) -> bool {
+ pub fn expired<'a, P>(&self, policy: P) -> bool
+ where P: Into<Option<&'a dyn Policy>>
+ {
+ let p = policy.into().unwrap_or(&DefaultPolicy(()));
if let Some(Signature::V4(sig)) = self.primary_key_signature() {
- sig.key_expired_at(self.primary(), tm)
- } else {
- false
- }
- }
-
- /// Returns whether or not the TPK is alive.
- pub fn alive(&self) -> bool {
- if let Some(sig) = self.primary_key_signature() {
- sig.key_alive(self.primary())
+ sig.key_expired_at(self.primary(), p.current_time())
} else {
false
}
}
/// Returns whether or not the key is alive at the given time.
- pub fn alive_at(&self, tm: time::Tm) -> bool {
+ pub fn alive<'a, P>(&self, policy: P) -> bool
+ where P: Into<Option<&'a dyn Policy>>
+ {
+ let p = policy.into().unwrap_or(&DefaultPolicy(()));
if let Some(sig) = self.primary_key_signature() {
- sig.key_alive_at(self.primary(), tm)
+ sig.key_alive_at(self.primary(), p.current_time())
} else {
false
}
@@ -3548,7 +3530,7 @@ mod test {
assert_eq!(sigtype, SignatureType::PositiveCertificate,
"{:#?}", tpk);
- let revoked = tpk.revocation_status();
+ let revoked = tpk.revocation_status(None);
if direct_revoked {
assert_match!(RevocationStatus::Revoked(_) = revoked,
"{:#?}", tpk);
@@ -3635,7 +3617,7 @@ mod test {
let (tpk, _) = TPKBuilder::autocrypt(None, Some("Test"))
.generate().unwrap();
assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
- tpk.revocation_status());
+ tpk.revocation_status(None));
let mut keypair = tpk.primary().clone().into_keypair().unwrap();
let sig = tpk.revoke(&mut keypair,
@@ -3644,7 +3626,7 @@ mod test {
assert_eq!(sig.sigtype(), SignatureType::KeyRevocation);
let tpk = tpk.merge_packets(vec![sig.into()]).unwrap();
- assert_match!(RevocationStatus::Revoked(_) = tpk.revocation_status());
+ assert_match!(RevocationStatus::Revoked(_) = tpk.revocation_status(None));
}
#[test]
@@ -3670,7 +3652,7 @@ mod test {
assert_eq!(sig.sigtype(), SignatureType::CertificateRevocation);
let tpk = tpk.merge_packets(vec![sig.into()]).unwrap();
assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
- tpk.revocation_status());
+ tpk.revocation_status(None));
let uid = tpk.userids().skip(1).next().unwrap();
assert_match!(RevocationStatus::Revoked(_) = uid.revoked(None));
@@ -3748,13 +3730,16 @@ mod test {
let te1 = t1 - time::Duration::days((300.0 * f1) as i64);
let t12 = t1 + time::Duration::days((300.0 * f2) as i64);
let t23 = t2 + time::Duration::days((300.0 * f3) as i64);
- assert_eq!(tpk.revocation_status_at(te1), RevocationStatus::NotAsFarAsWeKnow);
- assert_eq!(tpk.revocation_status_at(t12), RevocationStatus::NotAsFarAsWeKnow);
- match tpk.revocation_status_at(t23) {
+ assert_eq!(tpk.revocation_status(&te1 as &Policy),
+ RevocationStatus::NotAsFarAsWeKnow);
+ assert_eq!(tpk.revocation_status(&t12 as &Policy),
+ RevocationStatus::NotAsFarAsWeKnow);
+ match tpk.revocation_status(&t23 as &Policy) {
RevocationStatus::Revoked(_) => {}
_ => unreachable!(),
}
- assert_eq!(tpk.revocation_status_at(time::now_utc()), RevocationStatus::NotAsFarAsWeKnow);
+ assert_eq!(tpk.revocation_status(None),
+ RevocationStatus::NotAsFarAsWeKnow);
}
#[test]
diff --git a/sqv/src/sqv.rs b/sqv/src/sqv.rs
index 873ca9e8..e09dc7c9 100644
--- a/sqv/src/sqv.rs
+++ b/sqv/src/sqv.rs
@@ -14,7 +14,7 @@ use std::process::exit;
use std::fs::File;
use std::collections::{HashMap, HashSet};
-use openpgp::{TPK, Packet, packet::Signature, KeyID, RevocationStatus};
+use openpgp::{TPK, Packet, packet::Signature, KeyID, RevocationStatus, Policy};
use openpgp::constants::HashAlgorithm;
use openpgp::crypto::Hash;
use openpgp::parse::{Parse, PacketParserResult, PacketParser};
@@ -273,7 +273,7 @@ fn real_main() -> Result<(), failure::Error> {
}
}
- if tpk.revocation_status_at(t)
+ if tpk.revocation_status(&t as &Policy)
!= RevocationStatus::NotAsFarAsWeKnow
{
eprintln!(
diff --git a/tool/src/commands/inspect.rs b/tool/src/commands/inspect.rs
index bb7257de..324c0e03 100644
--- a/tool/src/commands/inspect.rs
+++ b/tool/src/commands/inspect.rs
@@ -130,7 +130,7 @@ fn inspect_tpk(output: &mut io::Write, tpk: &openpgp::TPK,
if tpk.is_tsk() { "Secret" } else { "Public" })?;
writeln!(output)?;
writeln!(output, " Fingerprint: {}", tpk.fingerprint())?;
- inspect_revocation(output, "", tpk.revocation_status())?;
+ inspect_revocation(output, "", tpk.revocation_status(None))?;
inspect_key(output, "", tpk.primary(), tpk.primary_key_signature(),
tpk.certifications(),
print_keygrips, print_certifications)?;