summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi/src/error.rs2
-rw-r--r--openpgp-ffi/src/cert.rs5
-rw-r--r--openpgp-ffi/src/error.rs6
-rw-r--r--openpgp-ffi/src/parse/stream.rs6
-rw-r--r--openpgp/src/cert/builder.rs24
-rw-r--r--openpgp/src/cert/key_amalgamation.rs154
-rw-r--r--openpgp/src/cert/keyiter.rs14
-rw-r--r--openpgp/src/lib.rs4
-rw-r--r--openpgp/src/parse/stream.rs16
-rw-r--r--sqv/src/sqv.rs2
10 files changed, 132 insertions, 101 deletions
diff --git a/ffi/src/error.rs b/ffi/src/error.rs
index 1bcf051c..5b1c6ea0 100644
--- a/ffi/src/error.rs
+++ b/ffi/src/error.rs
@@ -74,6 +74,8 @@ impl<'a> FromSequoiaError<'a> for Status {
Status::Expired,
&openpgp::Error::NotYetLive(_) =>
Status::NotYetLive,
+ &openpgp::Error::NoBindingSignature(_) =>
+ Status::NoBindingSignature,
openpgp::Error::__Nonexhaustive => unreachable!(),
}
}
diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs
index 2d18ff18..cfa490ac 100644
--- a/openpgp-ffi/src/cert.rs
+++ b/openpgp-ffi/src/cert.rs
@@ -767,9 +767,8 @@ pub extern "C" fn pgp_cert_valid_key_iter_next<'a>(
iter_wrapper.next_called = true;
if let Some(ka) = iter_wrapper.iter.next() {
- // XXX: Shouldn't assume the current time.
- let sig = ka.binding_signature(None);
- let rs = ka.revoked(None);
+ let sig = ka.binding_signature();
+ let rs = ka.revoked();
let key = ka.key();
if let Some(ptr) = sigo {
diff --git a/openpgp-ffi/src/error.rs b/openpgp-ffi/src/error.rs
index 2277d9a2..43b2b63d 100644
--- a/openpgp-ffi/src/error.rs
+++ b/openpgp-ffi/src/error.rs
@@ -153,6 +153,9 @@ pub enum Status {
/// Not yet live.
NotYetLive = -31,
+
+ /// No binding signature.
+ NoBindingSignature = -32,
}
/// Returns the error message.
@@ -195,6 +198,7 @@ pub extern "C" fn pgp_status_to_string(status: Status) -> *const c_char {
UnsupportedCert => "Cert not supported\x00",
Expired => "Expired\x00",
NotYetLive => "Not yet live\x00",
+ NoBindingSignature => "No binding signature\x00",
}.as_bytes().as_ptr() as *const c_char
}
@@ -250,6 +254,8 @@ impl<'a> From<&'a failure::Error> for Status {
Status::Expired,
&openpgp::Error::NotYetLive(_) =>
Status::NotYetLive,
+ &openpgp::Error::NoBindingSignature(_) =>
+ Status::NoBindingSignature,
openpgp::Error::__Nonexhaustive => unreachable!(),
}
}
diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs
index ae3fde7a..49778ad1 100644
--- a/openpgp-ffi/src/parse/stream.rs
+++ b/openpgp-ffi/src/parse/stream.rs
@@ -190,7 +190,7 @@ fn $fn_name<'a>(
-> bool
{
use self::stream::VerificationResult::*;
- if let $variant { sig, cert, ka, time } = result.ref_raw() {
+ if let $variant { sig, cert, ka } = result.ref_raw() {
if let Some(mut p) = sig_r {
*unsafe { p.as_mut() } = sig.move_into_raw();
}
@@ -207,10 +207,10 @@ fn $fn_name<'a>(
}
if let Some(mut p) = binding_r {
*unsafe { p.as_mut() } =
- ka.binding_signature(*time).move_into_raw();
+ ka.binding_signature().move_into_raw();
}
if let Some(mut p) = revocation_status_r {
- *unsafe { p.as_mut() } = ka.revoked(*time).move_into_raw();
+ *unsafe { p.as_mut() } = ka.revoked().move_into_raw();
}
true
} else {
diff --git a/openpgp/src/cert/builder.rs b/openpgp/src/cert/builder.rs
index c33633da..d870be1f 100644
--- a/openpgp/src/cert/builder.rs
+++ b/openpgp/src/cert/builder.rs
@@ -655,22 +655,18 @@ mod tests {
assert!(sig.key_alive(key, now + 590 * s).is_ok());
assert!(! sig.key_alive(key, now + 610 * s).is_ok());
- let (sig, key) = cert.keys().policy(now).alive().revoked(false)
+ let ka = cert.keys().policy(now).alive().revoked(false)
.for_signing()
- .nth(0).map(|ka| {
- (ka.binding_signature(now).unwrap(), ka.key())
- }).unwrap();
- assert!(sig.key_alive(key, now).is_ok());
- assert!(sig.key_alive(key, now + 290 * s).is_ok());
- assert!(! sig.key_alive(key, now + 310 * s).is_ok());
+ .nth(0).unwrap();
+ assert!(ka.alive().is_ok());
+ assert!(ka.clone().set_time(now + 290 * s).alive().is_ok());
+ assert!(! ka.clone().set_time(now + 310 * s).alive().is_ok());
- let (sig, key) = cert.keys().policy(now).alive().revoked(false)
+ let ka = cert.keys().policy(now).alive().revoked(false)
.for_authentication()
- .nth(0).map(|ka| {
- (ka.binding_signature(now).unwrap(), ka.key())
- }).unwrap();
- assert!(sig.key_alive(key, now).is_ok());
- assert!(sig.key_alive(key, now + 590 * s).is_ok());
- assert!(! sig.key_alive(key, now + 610 * s).is_ok());
+ .nth(0).unwrap();
+ assert!(ka.alive().is_ok());
+ assert!(ka.clone().set_time(now + 590 * s).alive().is_ok());
+ assert!(! ka.clone().set_time(now + 610 * s).alive().is_ok());
}
}
diff --git a/openpgp/src/cert/key_amalgamation.rs b/openpgp/src/cert/key_amalgamation.rs
index 9d0f9ba5..62f846ae 100644
--- a/openpgp/src/cert/key_amalgamation.rs
+++ b/openpgp/src/cert/key_amalgamation.rs
@@ -1,4 +1,5 @@
use std::time;
+use std::time::SystemTime;
use std::convert::TryInto;
use std::convert::TryFrom;
use std::borrow::Borrow;
@@ -6,6 +7,7 @@ use std::borrow::Borrow;
use crate::{
Cert,
cert::KeyBinding,
+ Error,
packet::key,
packet::key::SecretKeyMaterial,
packet::Key,
@@ -16,17 +18,19 @@ use crate::{
};
/// A variant of `KeyAmalgamation` for primary keys.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
struct PrimaryKeyAmalgamation<'a, P: key::KeyParts> {
cert: &'a Cert,
binding: &'a KeyBinding<P, key::PrimaryRole>,
+ time: SystemTime,
}
/// A variant of `KeyAmalgamation` for subkeys.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
struct SubordinateKeyAmalgamation<'a, P: key::KeyParts> {
cert: &'a Cert,
binding: &'a KeyBinding<P, key::SubordinateRole>,
+ time: SystemTime,
}
/// The underlying `KeyAmalgamation` type.
@@ -34,36 +38,38 @@ struct SubordinateKeyAmalgamation<'a, P: key::KeyParts> {
/// We don't make this type public, because an enum's variant types
/// must also all be public, and we don't want that here. Wrapping
/// this in a struct means that we can hide that.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
enum KeyAmalgamation0<'a, P: key::KeyParts> {
Primary(PrimaryKeyAmalgamation<'a, P>),
Subordinate(SubordinateKeyAmalgamation<'a, P>),
}
/// A `Key` and its associated data.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct KeyAmalgamation<'a, P: key::KeyParts>(KeyAmalgamation0<'a, P>);
-impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::PrimaryRole>)>
+impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::PrimaryRole>, SystemTime)>
for KeyAmalgamation<'a, P>
where P: key::KeyParts
{
- fn from(x: (&'a Cert, &'a KeyBinding<P, key::PrimaryRole>)) -> Self {
+ fn from(x: (&'a Cert, &'a KeyBinding<P, key::PrimaryRole>, SystemTime)) -> Self {
KeyAmalgamation(KeyAmalgamation0::Primary(PrimaryKeyAmalgamation {
cert: x.0,
binding: x.1,
+ time: x.2,
}))
}
}
-impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::SubordinateRole>)>
+impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::SubordinateRole>, SystemTime)>
for KeyAmalgamation<'a, P>
where P: key::KeyParts
{
- fn from(x: (&'a Cert, &'a KeyBinding<P, key::SubordinateRole>)) -> Self {
+ fn from(x: (&'a Cert, &'a KeyBinding<P, key::SubordinateRole>, SystemTime)) -> Self {
KeyAmalgamation(KeyAmalgamation0::Subordinate(SubordinateKeyAmalgamation {
cert: x.0,
binding: x.1,
+ time: x.2,
}))
}
}
@@ -80,6 +86,7 @@ impl<'a> From<KeyAmalgamation<'a, key::PublicParts>>
PrimaryKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.into(),
+ time: ka.time,
})
)
}
@@ -88,6 +95,7 @@ impl<'a> From<KeyAmalgamation<'a, key::PublicParts>>
SubordinateKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.into(),
+ time: ka.time,
})
)
}
@@ -105,6 +113,7 @@ impl<'a> From<KeyAmalgamation<'a, key::SecretParts>>
PrimaryKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.into(),
+ time: ka.time,
})
)
}
@@ -113,6 +122,7 @@ impl<'a> From<KeyAmalgamation<'a, key::SecretParts>>
SubordinateKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.into(),
+ time: ka.time,
})
)
}
@@ -132,6 +142,7 @@ impl<'a> TryFrom<KeyAmalgamation<'a, key::PublicParts>>
PrimaryKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.try_into()?,
+ time: ka.time,
})
)
}
@@ -140,6 +151,7 @@ impl<'a> TryFrom<KeyAmalgamation<'a, key::PublicParts>>
SubordinateKeyAmalgamation {
cert: ka.cert,
binding: ka.binding.try_into()?,
+ time: ka.time,
})
)
}
@@ -160,44 +172,76 @@ impl<'a, P: 'a + key::KeyParts> KeyAmalgamation<'a, P> {
}
}
- /// Returns the key's binding signature at time `t`, if any.
- pub fn binding_signature<T>(&self, t: T) -> Option<&'a Signature>
+ /// Returns the amalgamation's reference time.
+ ///
+ /// For queries that are with respect to a point in time, this
+ /// determines that point in time. For instance, if a key is
+ /// created at `t_c` and expires at `t_e`, then
+ /// `KeyAmalgamation::alive` will return true if the reference
+ /// time is greater than or equal to `t_c` and less than `t_e`.
+ pub fn time(&self) -> SystemTime {
+ match self {
+ KeyAmalgamation(KeyAmalgamation0::Primary(ref h)) =>
+ h.time,
+ KeyAmalgamation(KeyAmalgamation0::Subordinate(ref h)) =>
+ h.time,
+ }
+ }
+
+ /// Changes the amalgamation's reference time.
+ ///
+ /// If `time` is `None`, the current time is used.
+ pub fn set_time<T>(mut self, time: T) -> Self
where T: Into<Option<time::SystemTime>>
{
+ let time = time.into().unwrap_or_else(SystemTime::now);
+ match self {
+ KeyAmalgamation(KeyAmalgamation0::Primary(ref mut h)) =>
+ h.time = time,
+ KeyAmalgamation(KeyAmalgamation0::Subordinate(ref mut h)) =>
+ h.time = time,
+ }
+
+ self
+ }
+
+ /// Returns the key's binding signature as of the reference time,
+ /// if any.
+ pub fn binding_signature(&self) -> Option<&'a Signature>
+ {
match self {
KeyAmalgamation(KeyAmalgamation0::Primary(ref h)) =>
- h.cert.primary_key_signature(t),
+ h.cert.primary_key_signature(self.time()),
KeyAmalgamation(KeyAmalgamation0::Subordinate(ref h)) =>
- h.binding.binding_signature(t),
+ h.binding.binding_signature(self.time()),
}
}
- /// Returns the key's revocation status at time `t`.
- pub fn revoked<T>(&self, t: T) -> RevocationStatus<'a>
- where T: Into<Option<time::SystemTime>>
+ /// Returns the key's revocation status as of the amalgamtion's
+ /// reference time.
+ pub fn revoked(&self) -> RevocationStatus<'a>
{
match self {
KeyAmalgamation(KeyAmalgamation0::Primary(ref h)) =>
- h.cert.revoked(t),
+ h.cert.revoked(self.time()),
KeyAmalgamation(KeyAmalgamation0::Subordinate(ref h)) =>
- h.binding.revoked(t),
+ h.binding.revoked(self.time()),
}
}
- /// Returns the key's key flags at time `time`.
- pub fn key_flags<T>(&self, time: T) -> Option<KeyFlags>
- where T: Into<Option<time::SystemTime>>
+ /// Returns the key's key flags as of the amalgamtion's
+ /// reference time.
+ pub fn key_flags(&self) -> Option<KeyFlags>
{
- self.binding_signature(time).map(|sig| sig.key_flags())
+ self.binding_signature().map(|sig| sig.key_flags())
}
/// Returns whether the key has at least one of the specified key
- /// flags at time `time`.
- pub fn has_any_key_flag<T, F>(&self, time: T, flags: F) -> bool
- where T: Into<Option<time::SystemTime>>,
- F: Borrow<KeyFlags>
+ /// flags as of the amalgamtion's reference time.
+ pub fn has_any_key_flag<F>(&self, flags: F) -> bool
+ where F: Borrow<KeyFlags>
{
- if let Some(our_flags) = self.key_flags(time) {
+ if let Some(our_flags) = self.key_flags() {
!(&our_flags & flags.borrow()).is_empty()
} else {
// We have no key flags.
@@ -205,52 +249,48 @@ impl<'a, P: 'a + key::KeyParts> KeyAmalgamation<'a, P> {
}
}
- /// Returns whether key is certification capable at time `time`.
- pub fn for_certification<T>(&self, time: T) -> bool
- where T: Into<Option<time::SystemTime>>
- {
- self.has_any_key_flag(time, KeyFlags::empty().set_certification(true))
+ /// Returns whether key is certification capable as of the
+ /// amalgamtion's reference time.
+ pub fn for_certification(&self) -> bool {
+ self.has_any_key_flag(KeyFlags::empty().set_certification(true))
}
- /// Returns whether key is signing capable at time `time`.
- pub fn for_signing<T>(&self, time: T) -> bool
- where T: Into<Option<time::SystemTime>>
- {
- self.has_any_key_flag(time, KeyFlags::empty().set_signing(true))
+ /// Returns whether key is signing capable as of the amalgamtion's
+ /// reference time.
+ pub fn for_signing(&self) -> bool {
+ self.has_any_key_flag(KeyFlags::empty().set_signing(true))
}
- /// Returns whether key is authentication capable at time `time`.
- pub fn for_authentication<T>(&self, time: T) -> bool
- where T: Into<Option<time::SystemTime>>
+ /// Returns whether key is authentication capable as of the
+ /// amalgamtion's reference time.
+ pub fn for_authentication(&self) -> bool
{
- self.has_any_key_flag(time, KeyFlags::empty().set_authentication(true))
+ self.has_any_key_flag(KeyFlags::empty().set_authentication(true))
}
- /// Returns whether key is intended for storage encryption at time
- /// `time`.
- pub fn for_storage_encryption<T>(&self, time: T) -> bool
- where T: Into<Option<std::time::SystemTime>>
+ /// Returns whether key is intended for storage encryption as of
+ /// the amalgamtion's reference time.
+ pub fn for_storage_encryption(&self) -> bool
{
- self.has_any_key_flag(time, KeyFlags::empty().set_storage_encryption(true))
+ self.has_any_key_flag(KeyFlags::empty().set_storage_encryption(true))
}
- /// Returns whether key is intended for transport encryption at
- /// time `time`.
- pub fn for_transport_encryption<T>(&self, time: T) -> bool
- where T: Into<Option<std::time::SystemTime>>
+ /// Returns whether key is intended for transport encryption as of the
+ /// amalgamtion's reference time.
+ pub fn for_transport_encryption(&self) -> bool
{
- self.has_any_key_flag(time, KeyFlags::empty().set_transport_encryption(true))
+ self.has_any_key_flag(KeyFlags::empty().set_transport_encryption(true))
}
- /// Returns whether the key is alive at time `time`.
- pub fn alive<T>(&self, time: T) -> bool
- where T: Into<Option<std::time::SystemTime>>,
- &'a Key<P, key::UnspecifiedRole>: From<&'a key::PublicKey>
+ /// Returns whether the key is alive as of the amalgamtion's
+ /// reference time.
+ pub fn alive(&self) -> Result<()>
+ where &'a Key<P, key::UnspecifiedRole>: From<&'a key::PublicKey>
{
- if let Some(sig) = self.binding_signature(None) {
- sig.key_alive(self.key(), time).is_ok()
+ if let Some(sig) = self.binding_signature() {
+ sig.key_alive(self.key(), self.time())
} else {
- false
+ Err(Error::NoBindingSignature(self.time()).into())
}
}
diff --git a/openpgp/src/cert/keyiter.rs b/openpgp/src/cert/keyiter.rs
index f235ec89..752c457f 100644
--- a/openpgp/src/cert/keyiter.rs
+++ b/openpgp/src/cert/keyiter.rs
@@ -351,16 +351,16 @@ impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> ValidKeyIter<'a, P, R> {
loop {
let ka : KeyAmalgamation<'a, key::PublicParts> = if ! self.primary {
self.primary = true;
- (cert, &cert.primary).into()
+ (cert, &cert.primary, self.time).into()
} else {
- (cert, self.subkey_iter.next()?).into()
+ (cert, self.subkey_iter.next()?, self.time).into()
};
let key = ka.key();
t!("Considering key: {:?}", key);
let binding_signature
- = if let Some(binding_signature) = ka.binding_signature(self.time) {
+ = if let Some(binding_signature) = ka.binding_signature() {
binding_signature
} else {
t!("No self-signature at time {:?}", self.time);
@@ -368,7 +368,7 @@ impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> ValidKeyIter<'a, P, R> {
};
if let Some(flags) = self.flags.as_ref() {
- if (&binding_signature.key_flags() & &flags).is_empty() {
+ if !ka.has_any_key_flag(flags) {
t!("Have flags: {:?}, want flags: {:?}... skipping.",
binding_signature.key_flags(), flags);
continue;
@@ -376,14 +376,14 @@ impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> ValidKeyIter<'a, P, R> {
}
if let Some(()) = self.alive {
- if let Err(err) = binding_signature.key_alive(key, self.time) {
+ if let Err(err) = ka.alive() {
t!("Key not alive: {:?}", err);
continue;
}
}
if let Some(want_revoked) = self.revoked {
- if let RevocationStatus::Revoked(_) = ka.revoked(self.time) {
+ if let RevocationStatus::Revoked(_) = ka.revoked() {
// The key is definitely revoked.
if ! want_revoked {
t!("Key revoked... skipping.");
@@ -534,7 +534,7 @@ impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> ValidKeyIter<'a, P, R>
/// .keys()
/// .policy(None)
/// .filter(|ka| {
- /// match ka.revoked(None) {
+ /// match ka.revoked() {
/// RevocationStatus::Revoked(_) =>
/// // It's definitely revoked, skip it.
/// false,
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index 56d88528..c436d3b5 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -272,6 +272,10 @@ pub enum Error {
#[fail(display = "Not live until {:?}", _0)]
NotYetLive(std::time::SystemTime),
+ /// No binding signature.
+ #[fail(display = "No binding signature at time {:?}", _0)]
+ NoBindingSignature(std::time::SystemTime),
+
/// This marks this enum as non-exhaustive. Do not use this
/// variant.
#[doc(hidden)] #[fail(display = "__Nonexhaustive")] __Nonexhaustive,
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index fda80f62..3926299f 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -178,9 +178,6 @@ pub enum VerificationResult<'a> {
/// The signing key that made the signature.
ka: KeyAmalgamation<'a, key::PublicParts>,
-
- /// The time at which the signature is evaluated.
- time: time::SystemTime,
},
/// The signature is good, but it is not alive at the specified
@@ -197,9 +194,6 @@ pub enum VerificationResult<'a> {
/// The signing key that made the signature.
ka: KeyAmalgamation<'a, key::PublicParts>,
-
- /// The time at which the signature is evaluated.
- time: time::SystemTime,
},
/// Unable to verify the signature because the key is missing.
@@ -218,9 +212,6 @@ pub enum VerificationResult<'a> {
/// The signing key that made the signature.
ka: KeyAmalgamation<'a, key::PublicParts>,
-
- /// The time at which the signature is evaluated.
- time: time::SystemTime,
},
}
@@ -699,20 +690,17 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> {
VerificationResult::GoodChecksum {
sig: sig.clone(),
cert, ka,
- time: self.time,
}
} else {
VerificationResult::NotAlive {
sig: sig.clone(),
cert, ka,
- time: self.time,
}
}
} else {
VerificationResult::BadChecksum {
sig: sig.clone(),
cert, ka,
- time: self.time,
}
}
);
@@ -1609,14 +1597,12 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
{
sig: sig.clone(),
cert, ka,
- time: self.time,
}
} else {
VerificationResult::GoodChecksum
{
sig: sig.clone(),
cert, ka,
- time: self.time,
}
}
} else {
@@ -1624,14 +1610,12 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
VerificationResult::GoodChecksum {
sig: sig.clone(),
cert, ka,
- time: self.time,
}
}
} else {
VerificationResult::BadChecksum {
sig: sig.clone(),
cert, ka,
- time: self.time,
}
}
);
diff --git a/sqv/src/sqv.rs b/sqv/src/sqv.rs
index e1859132..fec3e1ff 100644
--- a/sqv/src/sqv.rs
+++ b/sqv/src/sqv.rs
@@ -235,7 +235,7 @@ fn real_main() -> Result<(), failure::Error> {
// Find the right key.
for ka in cert.keys().policy(None) {
// Use the current binding signature.
- let binding = match ka.binding_signature(None) {
+ let binding = match ka.binding_signature() {
Some(b) => b,
None => continue,
};