summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2019-11-11 19:51:04 +0100
committerNeal H. Walfield <neal@pep.foundation>2019-11-19 11:04:05 +0100
commitec03e1614a48fbe30f1200cb18bb00c7135f5242 (patch)
tree363aa6030de4fcb00d727830acbc308703a20468 /openpgp-ffi
parenta5fade1d635d75e474294a06870251d8f617db08 (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.h103
-rw-r--r--openpgp-ffi/src/packet/signature.rs121
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.