summaryrefslogtreecommitdiffstats
path: root/openpgp/src/parse.rs
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2022-11-11 09:32:25 +0100
committerNeal H. Walfield <neal@pep.foundation>2022-11-11 21:01:46 +0100
commit53474e58493cc10a9e021fde5ca1048a86859f2b (patch)
tree38bf36070d7aa5fb87d0e790809bad1003f5c5f2 /openpgp/src/parse.rs
parent813f3f00a967eea210641103b5e64e0d31299ae6 (diff)
openpgp: Add support for verifying v3 signatures.
- RFC 4880 explicitly allows the use of v3 signatures, but adds: > Implementations SHOULD accept V3 signatures. Implementations > SHOULD generate V4 signatures. - In practice, rpm-based distributions are generating v3 signatures, and it will be awhile before we can actually stop supporting them. https://bugzilla.redhat.com/show_bug.cgi?id=2141686#c20 - Add support for parsing, verifying, and serializing v3 signatures (but not v3 certificates, and not generating v3 signatures!).
Diffstat (limited to 'openpgp/src/parse.rs')
-rw-r--r--openpgp/src/parse.rs130
1 files changed, 92 insertions, 38 deletions
diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs
index 79467efe..fe421c71 100644
--- a/openpgp/src/parse.rs
+++ b/openpgp/src/parse.rs
@@ -205,6 +205,7 @@ use crate::{
Container,
Header,
},
+ packet::signature::Signature3,
packet::signature::Signature4,
packet::prelude::*,
Packet,
@@ -1344,6 +1345,7 @@ impl Signature {
let version = php_try!(php.parse_u8("version"));
match version {
+ 3 => Signature3::parse(php),
4 => Signature4::parse(php),
_ => {
t!("Ignoring version {} packet.", version);
@@ -1358,48 +1360,14 @@ impl Signature {
-> Result<()> {
Signature4::plausible(bio, header)
}
-}
-impl Signature4 {
- // Parses a signature packet.
- fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>)
- -> Result<PacketParser<'a>>
+ fn parse_finish(indent: isize, mut pp: PacketParser,
+ typ: SignatureType, hash_algo: HashAlgorithm)
+ -> Result<PacketParser>
{
- let indent = php.recursion_depth();
- tracer!(TRACE, "Signature4::parse", indent);
+ tracer!(TRACE, "Signature::parse_finish", indent);
- make_php_try!(php);
-
- let typ = php_try!(php.parse_u8("type"));
- let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
- let hash_algo: HashAlgorithm =
- php_try!(php.parse_u8("hash_algo")).into();
- let hashed_area_len = php_try!(php.parse_be_u16("hashed_area_len"));
- let hashed_area
- = php_try!(SubpacketArea::parse(&mut php,
- hashed_area_len as usize,
- hash_algo));
- let unhashed_area_len = php_try!(php.parse_be_u16("unhashed_area_len"));
- let unhashed_area
- = php_try!(SubpacketArea::parse(&mut php,
- unhashed_area_len as usize,
- hash_algo));
- let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
- let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
- if ! pk_algo.for_signing() {
- return php.fail("not a signature algorithm");
- }
- let mpis = php_try!(
- crypto::mpi::Signature::_parse(pk_algo, &mut php));
-
- let typ = typ.into();
let need_hash = HashingMode::for_signature(hash_algo, typ);
- let mut pp = php.ok(Packet::Signature(Signature4::new(
- typ, pk_algo, hash_algo,
- hashed_area,
- unhashed_area,
- [digest_prefix1, digest_prefix2],
- mpis).into()))?;
// Locate the corresponding HashedReader and extract the
// computed hash.
@@ -1480,6 +1448,50 @@ impl Signature4 {
Ok(pp)
}
+}
+
+impl Signature4 {
+ // Parses a signature packet.
+ fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>)
+ -> Result<PacketParser<'a>>
+ {
+ let indent = php.recursion_depth();
+ tracer!(TRACE, "Signature4::parse", indent);
+
+ make_php_try!(php);
+
+ let typ = php_try!(php.parse_u8("type"));
+ let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
+ let hash_algo: HashAlgorithm =
+ php_try!(php.parse_u8("hash_algo")).into();
+ let hashed_area_len = php_try!(php.parse_be_u16("hashed_area_len"));
+ let hashed_area
+ = php_try!(SubpacketArea::parse(&mut php,
+ hashed_area_len as usize,
+ hash_algo));
+ let unhashed_area_len = php_try!(php.parse_be_u16("unhashed_area_len"));
+ let unhashed_area
+ = php_try!(SubpacketArea::parse(&mut php,
+ unhashed_area_len as usize,
+ hash_algo));
+ let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
+ let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
+ if ! pk_algo.for_signing() {
+ return php.fail("not a signature algorithm");
+ }
+ let mpis = php_try!(
+ crypto::mpi::Signature::_parse(pk_algo, &mut php));
+
+ let typ = typ.into();
+ let pp = php.ok(Packet::Signature(Signature4::new(
+ typ, pk_algo, hash_algo,
+ hashed_area,
+ unhashed_area,
+ [digest_prefix1, digest_prefix2],
+ mpis).into()))?;
+
+ Signature::parse_finish(indent, pp, typ, hash_algo)
+ }
/// Returns whether the data appears to be a signature (no promises).
fn plausible<T: BufferedReader<Cookie>>(
@@ -1527,6 +1539,48 @@ impl Signature4 {
}
}
+impl Signature3 {
+ // Parses a v3 signature packet.
+ fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>)
+ -> Result<PacketParser<'a>>
+ {
+ let indent = php.recursion_depth();
+ tracer!(TRACE, "Signature3::parse", indent);
+
+ make_php_try!(php);
+
+ let len = php_try!(php.parse_u8("hashed length"));
+ if len != 5 {
+ return php.fail("invalid length \
+ (a v3 sig has 5 bytes of hashed data)");
+ }
+ let typ = php_try!(php.parse_u8("type"));
+ let creation_time: Timestamp
+ = php_try!(php.parse_be_u32("creation_time")).into();
+ let issuer: KeyID
+ = KeyID::from_bytes(&php_try!(php.parse_bytes("issuer", 8))[..]);
+ let pk_algo: PublicKeyAlgorithm
+ = php_try!(php.parse_u8("pk_algo")).into();
+ let hash_algo: HashAlgorithm =
+ php_try!(php.parse_u8("hash_algo")).into();
+ let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
+ let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
+ if ! pk_algo.for_signing() {
+ return php.fail("not a signature algorithm");
+ }
+ let mpis = php_try!(
+ crypto::mpi::Signature::_parse(pk_algo, &mut php));
+
+ let typ = typ.into();
+ let pp = php.ok(Packet::Signature(Signature3::new(
+ typ, creation_time, issuer, pk_algo, hash_algo,
+ [digest_prefix1, digest_prefix2],
+ mpis).into()))?;
+
+ Signature::parse_finish(indent, pp, typ, hash_algo)
+ }
+}
+
impl_parse_generic_packet!(Signature);
#[test]