diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-02-19 12:18:01 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-02-19 12:46:58 +0100 |
commit | ef396882bc35a97d778e985cd69ebd5181852d8c (patch) | |
tree | 6e7945e1394ff82e5a72badc933ddac710c108cc | |
parent | 32174f69cd4d94b4f621f3273781d487e97fa031 (diff) |
openpgp: Split VerificationResult.
- Split VerificationResult into Result<GoodChecksum,
VerificationError>.
- Fixes #416.
-rw-r--r-- | guide/src/chapter_01.md | 52 | ||||
-rw-r--r-- | ipc/examples/gpg-agent-decrypt.rs | 33 | ||||
-rw-r--r-- | ipc/tests/gpg-agent.rs | 16 | ||||
-rw-r--r-- | openpgp-ffi/examples/decrypt-with.c | 39 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp.h | 32 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp/types.h | 8 | ||||
-rw-r--r-- | openpgp-ffi/src/parse/stream.rs | 159 | ||||
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 19 | ||||
-rw-r--r-- | openpgp/examples/generate-sign-verify.rs | 12 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 265 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 12 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 10 | ||||
-rw-r--r-- | sqv/src/sqv.rs | 38 | ||||
-rw-r--r-- | tool/src/commands/mod.rs | 69 |
14 files changed, 415 insertions, 349 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md index 0c891aab..75bc6896 100644 --- a/guide/src/chapter_01.md +++ b/guide/src/chapter_01.md @@ -126,17 +126,10 @@ fn main() { # // whether the signature checks out mathematically, we apply # // our policy. # match results.into_iter().next() { -# Some(VerificationResult::GoodChecksum { .. }) => +# Some(Ok(_)) => # good = true, -# Some(VerificationResult::NotAlive { .. }) => -# return Err(failure::err_msg( -# "Good, but not alive signature")), -# Some(VerificationResult::MissingKey { .. }) => -# return Err(failure::err_msg( -# "Missing key to verify signature")), -# Some(VerificationResult::Error { error, .. }) => -# return Err(failure::err_msg( -# format!("Bad signature: {:?}", error))), +# Some(Err(e)) => +# return Err(openpgp::Error::from(e).into()), # None => # return Err(failure::err_msg("No signature")), # } @@ -281,17 +274,10 @@ fn generate() -> openpgp::Result<openpgp::Cert> { # // whether the signature checks out mathematically, we apply # // our policy. # match results.into_iter().next() { -# Some(VerificationResult::GoodChecksum { .. }) => +# Some(Ok(_)) => # good = true, -# Some(VerificationResult::NotAlive { .. }) => -# return Err(failure::err_msg( -# "Good, but not alive signature")), -# Some(VerificationResult::MissingKey { .. }) => -# return Err(failure::err_msg( -# "Missing key to verify signature")), -# Some(VerificationResult::Error { error, .. }) => -# return Err(failure::err_msg( -# format!("Bad signature: {:?}", error))), +# Some(Err(e)) => +# return Err(openpgp::Error::from(e).into()), # None => # return Err(failure::err_msg("No signature")), # } @@ -436,17 +422,10 @@ fn sign(policy: &dyn Policy, # // whether the signature checks out mathematically, we apply # // our policy. # match results.into_iter().next() { -# Some(VerificationResult::GoodChecksum { .. }) => +# Some(Ok(_)) => # good = true, -# Some(VerificationResult::NotAlive { .. }) => -# return Err(failure::err_msg( -# "Good, but not alive signature")), -# Some(VerificationResult::MissingKey { .. }) => -# return Err(failure::err_msg( -# "Missing key to verify signature")), -# Some(VerificationResult::Error { error, .. }) => -# return Err(failure::err_msg( -# format!("Bad signature: {:?}", error))), +# Some(Err(e)) => +# return Err(openpgp::Error::from(e).into()), # None => # return Err(failure::err_msg("No signature")), # } @@ -602,17 +581,10 @@ impl<'a> VerificationHelper for Helper<'a> { // whether the signature checks out mathematically, we apply // our policy. match results.into_iter().next() { - Some(VerificationResult::GoodChecksum { .. }) => + Some(Ok(_)) => good = true, - Some(VerificationResult::NotAlive { .. }) => - return Err(failure::err_msg( - "Good, but not alive signature")), - Some(VerificationResult::MissingKey { .. }) => - return Err(failure::err_msg( - "Missing key to verify signature")), - Some(VerificationResult::Error { error, .. }) => - return Err(failure::err_msg( - format!("Bad signature: {:?}", error))), + Some(Err(e)) => + return Err(openpgp::Error::from(e).into()), None => return Err(failure::err_msg("No signature")), } diff --git a/ipc/examples/gpg-agent-decrypt.rs b/ipc/examples/gpg-agent-decrypt.rs index 97397363..16d3a85a 100644 --- a/ipc/examples/gpg-agent-decrypt.rs +++ b/ipc/examples/gpg-agent-decrypt.rs @@ -16,7 +16,8 @@ use crate::openpgp::parse::{ DecryptionHelper, Decryptor, VerificationHelper, - VerificationResult, + GoodChecksum, + VerificationError, MessageStructure, MessageLayer, }, @@ -125,7 +126,7 @@ impl<'a> VerificationHelper for Helper<'a> { } fn check(&mut self, structure: MessageStructure) -> failure::Fallible<()> { - use self::VerificationResult::*; + use self::VerificationError::*; for layer in structure.iter() { match layer { MessageLayer::Compression { algo } => @@ -140,20 +141,30 @@ impl<'a> VerificationHelper for Helper<'a> { MessageLayer::SignatureGroup { ref results } => for result in results { match result { - GoodChecksum { cert, .. } => { - eprintln!("Good signature from {}", cert); + Ok(GoodChecksum { ka, .. }) => { + eprintln!("Good signature from {}", ka.cert()); }, - NotAlive { sig, .. } => { - eprintln!("Good, but not alive signature from {:?}", - sig.get_issuers()); + Err(MalformedSignature { error, .. }) => { + eprintln!("Signature is malformed: {}", error); }, - MissingKey { .. } => { - eprintln!("No key to check signature"); + Err(MissingKey { sig, .. }) => { + let issuers = sig.get_issuers(); + eprintln!("Missing key {}, which is needed to \ + verify signature.", + issuers.first().unwrap().to_hex()); }, - Error { error, .. } => { - eprintln!("Error verifying signature: {}", + Err(UnboundKey { cert, error, .. }) => { + eprintln!("Signing key on {} is not bound: {}", + cert.fingerprint().to_hex(), error); + }, + Err(BadKey { ka, error, .. }) => { + eprintln!("Signing key on {} is bad: {}", + ka.cert().fingerprint().to_hex(), error); }, + Err(BadSignature { error, .. }) => { + eprintln!("Verifying signature: {}.", error); + }, } } } diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs index 2322e6d9..2b15aac7 100644 --- a/ipc/tests/gpg-agent.rs +++ b/ipc/tests/gpg-agent.rs @@ -166,18 +166,10 @@ fn sign() { // whether the signature checks out mathematically, we apply // our policy. match results.into_iter().next() { - Some(VerificationResult::GoodChecksum { .. }) => - good = true, - Some(VerificationResult::NotAlive { .. }) => - return Err(failure::err_msg( - "Good, but not live signature")), - Some(VerificationResult::MissingKey { .. }) => - return Err(failure::err_msg( - "Missing key to verify signature")), - Some(VerificationResult::Error { error, .. }) => - return Err(error), - None => - return Err(failure::err_msg("No signature")), + Some(Ok(_)) => good = true, + Some(Err(e)) => + return Err(openpgp::Error::from(e).into()), + None => (), } }, _ => return Err(failure::err_msg( diff --git a/openpgp-ffi/examples/decrypt-with.c b/openpgp-ffi/examples/decrypt-with.c index bae9c97a..489e70aa 100644 --- a/openpgp-ffi/examples/decrypt-with.c +++ b/openpgp-ffi/examples/decrypt-with.c @@ -76,6 +76,8 @@ check_cb (void *cookie_opaque, pgp_message_structure_t structure) pgp_key_t key = NULL; pgp_keyid_t keyid; char *keyid_str = NULL; + pgp_error_t err = NULL; + char *err_str = NULL; switch (pgp_verification_result_variant (result)) { case PGP_VERIFICATION_RESULT_GOOD_CHECKSUM: @@ -86,13 +88,10 @@ check_cb (void *cookie_opaque, pgp_message_structure_t structure) fprintf (stderr, "Good signature from %s\n", keyid_str); break; - case PGP_VERIFICATION_RESULT_NOT_ALIVE: - pgp_verification_result_not_alive (result, NULL, NULL, - &key, NULL, NULL); - keyid = pgp_key_keyid (key); - keyid_str = pgp_keyid_to_string (keyid); - fprintf (stderr, "Good checksum, but not alive signature from %s\n", - keyid_str); + case PGP_VERIFICATION_RESULT_MALFORMED_SIGNATURE: + pgp_verification_result_malformed_signature (result, NULL, &err); + err_str = pgp_error_to_string (err); + fprintf (stderr, "Malformed signature: %s\n", err_str); break; case PGP_VERIFICATION_RESULT_MISSING_KEY: @@ -102,20 +101,32 @@ check_cb (void *cookie_opaque, pgp_message_structure_t structure) fprintf (stderr, "No key to check signature from %s\n", keyid_str); break; - case PGP_VERIFICATION_RESULT_ERROR: { - pgp_error_t err; - pgp_verification_result_error (result, NULL, &err); - char *err_str = pgp_error_to_string (err); + case PGP_VERIFICATION_RESULT_UNBOUND_KEY: + pgp_verification_result_unbound_key (result, NULL, NULL, &err); + err_str = pgp_error_to_string (err); + fprintf (stderr, "Signing key not bound: %s\n", err_str); + break; + + case PGP_VERIFICATION_RESULT_BAD_KEY: + pgp_verification_result_bad_key (result, NULL, NULL, NULL, + NULL, NULL, &err); + err_str = pgp_error_to_string (err); + fprintf (stderr, "Bad signing key: %s\n", err_str); + break; + + case PGP_VERIFICATION_RESULT_BAD_SIGNATURE: + pgp_verification_result_bad_signature (result, NULL, NULL, NULL, + NULL, NULL, &err); + err_str = pgp_error_to_string (err); fprintf (stderr, "Bad signature: %s\n", err_str); - free (err_str); - pgp_error_free (err); break; - } default: assert (! "reachable"); } free (keyid_str); + free (err_str); + pgp_error_free (err); pgp_signature_free (sig); pgp_key_free (key); pgp_verification_result_free (result); diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h index 14afd4bc..bc098339 100644 --- a/openpgp-ffi/include/sequoia/openpgp.h +++ b/openpgp-ffi/include/sequoia/openpgp.h @@ -1718,17 +1718,29 @@ bool pgp_verification_result_good_checksum (pgp_verification_result_t, pgp_key_t *, pgp_signature_t *, pgp_revocation_status_t *); -bool pgp_verification_result_not_alive (pgp_verification_result_t, - pgp_signature_t *, - pgp_cert_t *, - pgp_key_t *, - pgp_signature_t *, - pgp_revocation_status_t *); +bool pgp_verification_result_malformed_signature (pgp_verification_result_t, + pgp_signature_t *, + pgp_error_t *); bool pgp_verification_result_missing_key (pgp_verification_result_t, - pgp_signature_t *); -bool pgp_verification_result_error (pgp_verification_result_t, - pgp_signature_t *, - pgp_error_t *); + pgp_signature_t *); +bool pgp_verification_result_unbound_key (pgp_verification_result_t, + pgp_signature_t *, + pgp_cert_t *, + pgp_error_t *); +bool pgp_verification_result_bad_key (pgp_verification_result_t, + pgp_signature_t *, + pgp_cert_t *, + pgp_key_t *, + pgp_signature_t *, + pgp_revocation_status_t *, + pgp_error_t *); +bool pgp_verification_result_bad_signature (pgp_verification_result_t, + pgp_signature_t *, + pgp_cert_t *, + pgp_key_t *, + pgp_signature_t *, + pgp_revocation_status_t *, + pgp_error_t *); /*/ /// Decrypts an OpenPGP message. diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h index 46deb520..4274ddbe 100644 --- a/openpgp-ffi/include/sequoia/openpgp/types.h +++ b/openpgp-ffi/include/sequoia/openpgp/types.h @@ -487,10 +487,12 @@ typedef struct pgp_verification_result *pgp_verification_result_t; typedef struct pgp_verification_result_iter *pgp_verification_result_iter_t; typedef enum pgp_verification_result_variant { - PGP_VERIFICATION_RESULT_GOOD_CHECKSUM = 1, + PGP_VERIFICATION_RESULT_GOOD_CHECKSUM = 0, + PGP_VERIFICATION_RESULT_MALFORMED_SIGNATURE = 1, PGP_VERIFICATION_RESULT_MISSING_KEY = 2, - PGP_VERIFICATION_RESULT_NOT_ALIVE = 3, - PGP_VERIFICATION_RESULT_ERROR = 4, + PGP_VERIFICATION_RESULT_UNBOUND_KEY = 3, + PGP_VERIFICATION_RESULT_BAD_KEY = 4, + PGP_VERIFICATION_RESULT_BAD_SIGNATURE = 5, /* Dummy value to make sure the enumeration has a defined size. Do not use this value. */ diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs index 5c9c92a3..6e549352 100644 --- a/openpgp-ffi/src/parse/stream.rs +++ b/openpgp-ffi/src/parse/stream.rs @@ -42,7 +42,7 @@ use crate::RefMutRaw; use crate::maybe_time; use super::super::{ - error::Status, + error::{Error, Status}, crypto, io, keyid, @@ -169,19 +169,24 @@ pub struct VerificationResult<'a>(stream::VerificationResult<'a>); fn pgp_verification_result_variant(result: *const VerificationResult) -> c_int { - use self::stream::VerificationResult::*; + use self::stream::VerificationError::*; match result.ref_raw() { - GoodChecksum { .. } => 1, - MissingKey { .. } => 2, - NotAlive { .. } => 3, - Error { .. } => 4, + Ok(_) => 0, + Err(MalformedSignature { .. }) => 1, + Err(MissingKey { .. }) => 2, + Err(UnboundKey { .. }) => 3, + Err(BadKey { .. }) => 4, + Err(BadSignature { .. }) => 5, } } -macro_rules! make_decomposition_fn { - ($fn_name:ident, $variant:path) => { +/// Decomposes a `VerificationResult::Ok(GoodChecksum)`. +/// +/// Returns `true` iff the given value is a +/// `VerificationResult::Ok(GoodChecksum)`, and returns the variants +/// members in `sig_r` and the like iff `sig_r != NULL`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" -fn $fn_name<'a>( +fn pgp_verification_result_good_checksum<'a>( result: *const VerificationResult<'a>, sig_r: Maybe<*mut Signature>, cert_r: Maybe<*mut Cert>, @@ -191,13 +196,13 @@ fn $fn_name<'a>( Maybe<*mut RevocationStatus<'a>>) -> bool { - use self::stream::VerificationResult::*; - if let $variant { sig, cert, ka } = result.ref_raw() { + use self::stream::GoodChecksum; + if let Ok(GoodChecksum { sig, ka }) = result.ref_raw() { if let Some(mut p) = sig_r { *unsafe { p.as_mut() } = sig.move_into_raw(); } if let Some(mut p) = cert_r { - *unsafe { p.as_mut() } = cert.move_into_raw(); + *unsafe { p.as_mut() } = ka.cert().move_into_raw(); } if let Some(mut p) = key_r { *unsafe { p.as_mut() } = { @@ -219,51 +224,51 @@ fn $fn_name<'a>( false } } - } -} -/// Decomposes a `VerificationResult::GoodChecksum`. +/// Decomposes a +/// `VerificationResult::Err(VerificationError::MalformedSignature { +/// .. })`. /// /// Returns `true` iff the given value is a -/// `VerificationResult::GoodChecksum`, and returns the variants members -/// in `sig_r` and the like iff `sig_r != NULL`. -make_decomposition_fn!(pgp_verification_result_good_checksum, GoodChecksum); - -/// Decomposes a `VerificationResult::NotAlive`. -/// -/// Returns `true` iff the given value is a -/// `VerificationResult::NotAlive`, and returns the variant's members -/// in `sig_r` and the like iff `sig_r != NULL`. +/// `VerificationResult::Err(VerificationError::MalformedSignature { +/// .. })`, and returns the variants members in `sig_r` and the like +/// iff `sig_r != NULL`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" -fn pgp_verification_result_not_alive<'a>( +fn pgp_verification_result_malformed_signature<'a>( result: *const VerificationResult<'a>, - sig_r: Maybe<*mut Signature>) + sig_r: Maybe<*mut Signature>, + error_r: Maybe<*mut Error>) -> bool { - use self::stream::VerificationResult::*; - if let NotAlive { sig, .. } = result.ref_raw() { + use self::stream::VerificationError::*; + if let Err(MalformedSignature { sig, error }) = result.ref_raw() { if let Some(mut p) = sig_r { *unsafe { p.as_mut() } = sig.move_into_raw(); } + if let Some(mut p) = error_r { + *unsafe { p.as_mut() } = error.move_into_raw(); + } true } else { false } } -/// Decomposes a `VerificationResult::MissingKey`. +/// Decomposes a +/// `VerificationResult::Err(VerificationError::MissingKey { .. })`. /// /// Returns `true` iff the given value is a -/// `VerificationResult::MissingKey`, and returns the variants members -/// in `sig_r` and the like iff `sig_r != NULL`. +/// `VerificationResult::Err(VerificationError::MissingKey { .. })`, +/// and returns the variants members in `sig_r` and the like iff +/// `sig_r != NULL`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_verification_result_missing_key<'a>( result: *const VerificationResult<'a>, sig_r: Maybe<*mut Signature>) -> bool { - use self::stream::VerificationResult::*; - if let MissingKey { sig, .. } = result.ref_raw() { + use self::stream::VerificationError::*; + if let Err(MissingKey { sig }) = result.ref_raw() { if let Some(mut p) = sig_r { *unsafe { p.as_mut() } = sig.move_into_raw(); } @@ -273,24 +278,30 @@ fn pgp_verification_result_missing_key<'a>( } } -/// Decomposes a `VerificationResult::Error`. +/// Decomposes a +/// `VerificationResult::Err(VerificationError::UnboundKey { .. })`. /// /// Returns `true` iff the given value is a -/// `VerificationResult::Error`, and returns the variants members -/// in `sig_r` and the like iff `sig_r != NULL`. +/// `VerificationResult::Err(VerificationError::UnboundKey { .. })`, +/// and returns the variants members in `sig_r` and the like iff +/// `sig_r != NULL`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" -fn pgp_verification_result_error<'a>( +fn pgp_verification_result_unbound_key<'a>( result: *const VerificationResult<'a>, sig_r: Maybe<*mut Signature>, - err_r: Maybe<*mut crate::error::Error>) + cert_r: Maybe<*mut Cert>, + error_r: Maybe<*mut Error>) -> bool { - use self::stream::VerificationResult::*; - if let Error { sig, error, .. } = result.ref_raw() { + use self::stream::VerificationError::*; + if let Err(UnboundKey { sig, cert, error }) = result.ref_raw() { if let Some(mut p) = sig_r { *unsafe { p.as_mut() } = sig.move_into_raw(); } - if let Some(mut p) = err_r { + if let Some(mut p) = cert_r { + *unsafe { p.as_mut() } = cert.move_into_raw(); + } + if let Some(mut p) = error_r { *unsafe { p.as_mut() } = error.move_into_raw(); } true @@ -299,6 +310,72 @@ fn pgp_verification_result_error<'a>( } } +macro_rules! make_decomposition_fn { + ($fn_name:ident, $variant:path) => { +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" +fn $fn_name<'a>( + result: *const VerificationResult<'a>, + sig_r: Maybe<*mut Signature>, + cert_r: Maybe<*mut Cert>, + key_r: Maybe<*mut Key>, + binding_r: Maybe<*mut Signature>, + revocation_status_r: + Maybe<*mut RevocationStatus<'a>>, + error_r: Maybe<*mut Error>) + -> bool +{ + use self::stream::VerificationError::*; + if let Err($variant { sig, ka, error }) = result.ref_raw() { + if let Some(mut p) = sig_r { + *unsafe { p.as_mut() } = sig.move_into_raw(); + } + if let Some(mut p) = cert_r { + *unsafe { p.as_mut() } = ka.cert().move_into_raw(); + } + if let Some(mut p) = key_r { + *unsafe { p.as_mut() } = { + let key = ka.key() + .mark_parts_unspecified_ref() + .mark_role_unspecified_ref(); + key.move_into_raw() + }; + } + if let Some(mut p) = binding_r { + *unsafe { p.as_mut() } = + ka.binding_signature().move_into_raw(); + } + if let Some(mut p) = revocation_status_r { + *unsafe { p.as_mut() } = ka.revoked().move_into_raw(); + } + if let Some(mut p) = error_r { + *unsafe { p.as_mut() } = error.move_into_raw(); + } + true + } else { + false + } +} + } +} + +/// Decomposes a +/// `VerificationResult::Err(VerificationError::BadKey { .. })`. +/// +/// Returns `true` iff the given value is a +/// `VerificationResult::Err(VerificationError::BadKey { .. })`, +/// and returns the variants members in `sig_r` and the like iff +/// `sig_r != NULL`. +make_decomposition_fn!(pgp_verification_result_bad_key, BadKey); + +/// Decomposes a +/// `VerificationResult::Err(VerificationError::BadSignature { .. })`. +/// +/// Returns `true` iff the given value is a +/// `VerificationResult::Err(VerificationError::BadSignature { .. })`, +/// and returns the variants members in `sig_r` and the like iff +/// `sig_r != NULL`. +make_decomposition_fn!(pgp_verification_result_bad_signature, BadSignature); + /// Passed as the first argument to the callbacks used by pgp_verify /// and pgp_decrypt. pub struct HelperCookie { diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index c4b9f56a..ca84a918 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -16,7 +16,7 @@ use crate::openpgp::parse::{ DecryptionHelper, Decryptor, VerificationHelper, - VerificationResult, + GoodChecksum, MessageStructure, MessageLayer, }, @@ -108,7 +108,6 @@ impl VerificationHelper for Helper { } fn check(&mut self, structure: MessageStructure) -> failure::Fallible<()> { - use self::VerificationResult::*; for layer in structure.iter() { match layer { MessageLayer::Compression { algo } => @@ -123,19 +122,11 @@ impl VerificationHelper for Helper { MessageLayer::SignatureGroup { ref results } => for result in results { match result { - GoodChecksum { cert, .. } => { - eprintln!("Good signature from {}", cert); - }, - NotAlive { sig, .. } => { - eprintln!("Good, but not alive signature from {:?}", - sig.get_issuers()); - }, - MissingKey { .. } => { - eprintln!("No key to check signature"); - }, - Error { error, .. } => { - eprintln!("Error: {}", error); + Ok(GoodChecksum { ka, .. }) => { + eprintln!("Good signature from {}", ka.cert()); }, + Err(e) => + eprintln!("Error: {:?}", e), } |