diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-11-11 19:51:04 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-11-19 11:04:05 +0100 |
commit | ec03e1614a48fbe30f1200cb18bb00c7135f5242 (patch) | |
tree | 363aa6030de4fcb00d727830acbc308703a20468 /openpgp-ffi | |
parent | a5fade1d635d75e474294a06870251d8f617db08 (diff) |
openpgp: Be tolerant when deciding wheter a signature is alive.
- Consider the following scenario: computer A's clock says 9:00.00
and signs and sends a message to computer B. Computer B's clock
says 8:59.59, it receives the message and tries to verify it.
From Computer B's perspective, the signature is not valid, because
it was generated in the future.
- This situation occured, because the two clocks were not completely
synchronized. Unfortunately, a few seconds of clock skew are not
unusual, particularly when dealing with VMs.
- Since it is almost always better to consider such messages as
valid, be tolerant when deciding whether a signature is alive.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp.h | 103 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/signature.rs | 121 |
2 files changed, 213 insertions, 11 deletions
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h index 0f41d6ed..6aeca8e9 100644 --- a/openpgp-ffi/include/sequoia/openpgp.h +++ b/openpgp-ffi/include/sequoia/openpgp.h @@ -381,14 +381,109 @@ bool pgp_signature_is_group_key(pgp_signature_t signature); /*/ /// Returns whether the signature is alive at the specified time. /// -/// If `when` is 0, then the current time is used. -/// -/// A signature is alive if the creation date is in the past, and the -/// signature has not expired at the specified time. +/// A signature is considered to be alive if `creation time - +/// tolerance <= time` and `time <= expiration time`. +/// +/// If `time` is 0, uses the current time. +/// +/// This function uses the default tolerance. If you want to specify +/// a different tolerance (or no tolerance), then use +/// `pgp_signature_alive_with_tolerance`. +/// +/// Some tolerance for clock skew is sometimes necessary, because +/// although most computers synchronize their clock with a time +/// server, up to a few seconds of clock skew are not unusual in +/// practice. And, even worse, several minutes of clock skew appear +/// to be not uncommon on virtual machines. +/// +/// Not accounting for clock skew can result in signatures being +/// unexpectedly considered invalid. Consider: computer A sends a +/// message to computer B at 9:00, but computer B, whose clock says +/// the current time is 8:59, rejects it, because the signature +/// appears to have been made in the future. This is particularly +/// problematic for low-latency protocols built on top of OpenPGP, +/// e.g., state synchronization between two MUAs via a shared IMAP +/// folder. +/// +/// Being tolerant to potential clock skew is not always appropriate. +/// For instance, when determining a User ID's current self signature +/// at time `t`, we don't ever want to consider a self-signature made +/// after `t` to be valid, even if it was made just a few moments +/// after `t`. This goes doubly so for soft revocation certificates: +/// the user might send a message that she is retiring, and then +/// immediately create a soft revocation. The soft revocation should +/// not invalidate the message. +/// +/// Unfortunately, in many cases, whether we should account for clock +/// skew or not depends on application-specific context. As a rule of +/// thumb, if the time and the timestamp come from different sources, +/// you probably want to account for clock skew. +/// +/// Note that [Section 5.2.3.4 of RFC 4880] states that "[[A Signature +/// Creation Time subpacket]] MUST be present in the hashed area." +/// Consequently, if such a packet does not exist, but a "Signature +/// Expiration Time" subpacket exists, we conservatively treat the +/// signature as expired, because there is no way to evaluate the +/// expiration time. +/// +/// [Section 5.2.3.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4 /*/ bool pgp_signature_alive(pgp_signature_t signature, time_t when); /*/ +/// Returns whether the signature is alive at the specified time. +/// +/// A signature is considered to be alive if `creation time - +/// tolerance <= time` and `time <= expiration time`. +/// +/// If `time` is 0, uses the current time. +/// +/// If `tolerance` is 0, uses no tolerance. To ensure consistency +/// across callers, you should use the default tolerance (i.e., use +/// `pgp_signature_alive`). +/// +/// Some tolerance for clock skew is sometimes necessary, because +/// although most computers synchronize their clock with a time +/// server, up to a few seconds of clock skew are not unusual in +/// practice. And, even worse, several minutes of clock skew appear +/// to be not uncommon on virtual machines. +/// +/// Not accounting for clock skew can result in signatures being +/// unexpectedly considered invalid. Consider: computer A sends a +/// message to computer B at 9:00, but computer B, whose clock says +/// the current time is 8:59, rejects it, because the signature +/// appears to have been made in the future. This is particularly +/// problematic for low-latency protocols built on top of OpenPGP, +/// e.g., state synchronization between two MUAs via a shared IMAP +/// folder. +/// +/// Being tolerant to potential clock skew is not always appropriate. +/// For instance, when determining a User ID's current self signature +/// at time `t`, we don't ever want to consider a self-signature made +/// after `t` to be valid, even if it was made just a few moments +/// after `t`. This goes doubly so for soft revocation certificates: +/// the user might send a message that she is retiring, and then +/// immediately create a soft revocation. The soft revocation should +/// not invalidate the message. +/// +/// Unfortunately, in many cases, whether we should account for clock +/// skew or not depends on application-specific context. As a rule of +/// thumb, if the time and the timestamp come from different sources, +/// you probably want to account for clock skew. +/// +/// Note that [Section 5.2.3.4 of RFC 4880] states that "[[A Signature +/// Creation Time subpacket]] MUST be present in the hashed area." +/// Consequently, if such a packet does not exist, but a "Signature +/// Expiration Time" subpacket exists, we conservatively treat the +/// signature as expired, because there is no way to evaluate the +/// expiration time. +/// +/// [Section 5.2.3.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4 +/*/ +bool pgp_signature_alive_with_tolerance(pgp_signature_t signature, + time_t time, unsigned int tolerance); + +/*/ /// Returns whether the signature is expired at the specified time. /// /// If `when` is 0, then the current time is used. diff --git a/openpgp-ffi/src/packet/signature.rs b/openpgp-ffi/src/packet/signature.rs index 636318b3..2b1b301e 100644 --- a/openpgp-ffi/src/packet/signature.rs +++ b/openpgp-ffi/src/packet/signature.rs @@ -8,6 +8,7 @@ //! [Section 5.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2 use libc::time_t; +use libc::c_uint; extern crate sequoia_openpgp as openpgp; use super::Packet; @@ -118,18 +119,124 @@ fn pgp_signature_is_group_key(sig: *const Signature) -> bool { /// Returns whether the signature is alive at the specified time. /// -/// If `when` is 0, then the current time is used. +/// A signature is considered to be alive if `creation time - +/// tolerance <= time` and `time <= expiration time`. /// -/// A signature is alive if the creation date is in the past, and the -/// signature has not expired at the specified time. +/// If `time` is 0, uses the current time. +/// +/// This function uses the default tolerance. If you want to specify +/// a different tolerance (or no tolerance), then use +/// `pgp_signature_alive_with_tolerance`. +/// +/// Some tolerance for clock skew is sometimes necessary, because +/// although most computers synchronize their clock with a time +/// server, up to a few seconds of clock skew are not unusual in +/// practice. And, even worse, several minutes of clock skew appear +/// to be not uncommon on virtual machines. +/// +/// Not accounting for clock skew can result in signatures being +/// unexpectedly considered invalid. Consider: computer A sends a +/// message to computer B at 9:00, but computer B, whose clock says +/// the current time is 8:59, rejects it, because the signature +/// appears to have been made in the future. This is particularly +/// problematic for low-latency protocols built on top of OpenPGP, +/// e.g., state synchronization between two MUAs via a shared IMAP +/// folder. +/// +/// Being tolerant to potential clock skew is not always appropriate. +/// For instance, when determining a User ID's current self signature +/// at time `t`, we don't ever want to consider a self-signature made +/// after `t` to be valid, even if it was made just a few moments +/// after `t`. This goes doubly so for soft revocation certificates: +/// the user might send a message that she is retiring, and then +/// immediately create a soft revocation. The soft revocation should +/// not invalidate the message. +/// +/// Unfortunately, in many cases, whether we should account for clock +/// skew or not depends on application-specific context. As a rule of +/// thumb, if the time and the timestamp come from different sources, +/// you probably want to account for clock skew. +/// +/// Note that [Section 5.2.3.4 of RFC 4880] states that "[[A Signature +/// Creation Time subpacket]] MUST be present in the hashed area." +/// Consequently, if such a packet does not exist, but a "Signature +/// Expiration Time" subpacket exists, we conservatively treat the +/// signature as expired, because there is no way to evaluate the +/// expiration time. +/// +/// [Section 5.2.3.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" -fn pgp_signature_alive(sig: *const Signature, when: time_t) -> bool { - let t = if when == 0 { +fn pgp_signature_alive(sig: *const Signature, time: time_t) + -> bool +{ + let time = if time == 0 { None } else { - Some(time::at(time::Timespec::new(when as i64, 0))) + Some(time::at(time::Timespec::new(time as i64, 0))) + }; + sig.ref_raw().signature_alive(time, None) +} + +/// Returns whether the signature is alive at the specified time. +/// +/// A signature is considered to be alive if `creation time - +/// tolerance <= time` and `time <= expiration time`. +/// +/// If `time` is 0, uses the current time. +/// +/// If `tolerance` is 0, uses no tolerance. To ensure consistency +/// across callers, you should use the default tolerance (i.e., use +/// `pgp_signature_alive`). +/// +/// Some tolerance for clock skew is sometimes necessary, because +/// although most computers synchronize their clock with a time +/// server, up to a few seconds of clock skew are not unusual in +/// practice. And, even worse, several minutes of clock skew appear +/// to be not uncommon on virtual machines. +/// +/// Not accounting for clock skew can result in signatures being +/// unexpectedly considered invalid. Consider: computer A sends a +/// message to computer B at 9:00, but computer B, whose clock says +/// the current time is 8:59, rejects it, because the signature +/// appears to have been made in the future. This is particularly +/// problematic for low-latency protocols built on top of OpenPGP, +/// e.g., state synchronization between two MUAs via a shared IMAP +/// folder. +/// +/// Being tolerant to potential clock skew is not always appropriate. +/// For instance, when determining a User ID's current self signature +/// at time `t`, we don't ever want to consider a self-signature made +/// after `t` to be valid, even if it was made just a few moments +/// after `t`. This goes doubly so for soft revocation certificates: +/// the user might send a message that she is retiring, and then +/// immediately create a soft revocation. The soft revocation should +/// not invalidate the message. +/// +/// Unfortunately, in many cases, whether we should account for clock +/// skew or not depends on application-specific context. As a rule of +/// thumb, if the time and the timestamp come from different sources, +/// you probably want to account for clock skew. +/// +/// Note that [Section 5.2.3.4 of RFC 4880] states that "[[A Signature +/// Creation Time subpacket]] MUST be present in the hashed area." +/// Consequently, if such a packet does not exist, but a "Signature +/// Expiration Time" subpacket exists, we conservatively treat the +/// signature as expired, because there is no way to evaluate the +/// expiration time. +/// +/// [Section 5.2.3.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4 +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" +fn pgp_signature_alive_with_tolerance(sig: *const Signature, + time: time_t, tolerance: c_uint) + -> bool +{ + let time = if time == 0 { + None + } else { + Some(time::at(time::Timespec::new(time as i64, 0))) }; - sig.ref_raw().signature_alive(t) + let tolerance = time::Duration::seconds(tolerance as i64); + sig.ref_raw().signature_alive(time, Some(tolerance)) } /// Returns whether the signature is expired at the specified time. |