diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-11-16 13:54:56 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-11-24 13:27:51 +0100 |
commit | fbbe3cf4ca6b6b1881160925f869065e8f3df58e (patch) | |
tree | 0a5313dac497810f9b7a06b6562ab89de2fd35e0 /openpgp/src | |
parent | 03598e4da99dbaf4c9f978e8f6f57ce3f6720b48 (diff) |
openpgp: Align hashing of compound objects with primitive objects.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/cert.rs | 19 | ||||
-rw-r--r-- | openpgp/src/crypto/hash.rs | 113 | ||||
-rw-r--r-- | openpgp/src/packet/signature.rs | 103 |
3 files changed, 120 insertions, 115 deletions
diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index f6232bc6..65a47486 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -1482,9 +1482,12 @@ impl Cert { .into_iter() { // Use hash prefix as heuristic. - match Signature::$hash_method(&sig, - self.primary.key(), - $($verify_args),*) { + let key = self.primary.key(); + match sig.hash_algo().context().and_then(|mut ctx| { + Signature::$hash_method(&mut ctx, &sig, key, + $($verify_args),*); + ctx.into_digest() + }) { Ok(hash) => { if &sig.digest_prefix()[..] == &hash[..2] { // See if we can get the key for a @@ -1706,8 +1709,14 @@ impl Cert { } } else { // Use hash prefix as heuristic. - if let Ok(hash) = Signature::$hash_method( - &sig, self.primary.key(), $($verify_args),*) { + let key = self.primary.key(); + if let Ok(hash) = sig.hash_algo().context() + .and_then(|mut ctx| { + Signature::$hash_method(&mut ctx, &sig, key, + $($verify_args),*); + ctx.into_digest() + }) + { if &sig.digest_prefix()[..] == &hash[..2] { t!("Sig {:02X}{:02X}, {:?} \ was out of place. Likely belongs to {}.", diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs index 5517d205..9221e070 100644 --- a/openpgp/src/crypto/hash.rs +++ b/openpgp/src/crypto/hash.rs @@ -113,6 +113,13 @@ impl Context { pub fn digest<D: AsMut<[u8]>>(&mut self, mut digest: D) -> Result<()> { self.ctx.digest(digest.as_mut()) } + + /// Finalizes the hash function and computes the digest. + pub fn into_digest(mut self) -> Result<Vec<u8>> { + let mut digest = vec![0u8; self.digest_size()]; + self.digest(&mut digest)?; + Ok(digest) + } } impl io::Write for Context { @@ -382,112 +389,81 @@ impl Hash for signature::SignatureFields { /// <a name="hashing-functions"></a> impl Signature { /// Computes the message digest of standalone signatures. - pub fn hash_standalone(sig: &signature::SignatureFields) - -> Result<Vec<u8>> + pub fn hash_standalone(hash: &mut Context, + sig: &signature::SignatureFields) { - let mut h = sig.hash_algo().context()?; - - sig.hash(&mut h); - - let mut digest = vec![0u8; h.digest_size()]; - h.digest(&mut digest)?; - Ok(digest) + sig.hash(hash); } /// Computes the message digest of timestamp signatures. - pub fn hash_timestamp(sig: &signature::SignatureFields) - -> Result<Vec<u8>> + pub fn hash_timestamp(hash: &mut Context, + sig: &signature::SignatureFields) { - Self::hash_standalone(sig) + Self::hash_standalone(hash, sig); } /// Returns the message digest of the direct key signature over /// the specified primary key. - pub fn hash_direct_key<P>(sig: &signature::SignatureFields, + pub fn hash_direct_key<P>(hash: &mut Context, + sig: &signature::SignatureFields, key: &Key<P, key::PrimaryRole>) - -> Result<Vec<u8>> where P: key::KeyParts, { - - let mut h = sig.hash_algo().context()?; - - key.hash(&mut h); - sig.hash(&mut h); - - let mut digest = vec![0u8; h.digest_size()]; - h.digest(&mut digest)?; - Ok(digest) + key.hash(hash); + sig.hash(hash); } /// Returns the message digest of the subkey binding over the /// specified primary key and subkey. - pub fn hash_subkey_binding<P, Q>(sig: &signature::SignatureFields, + pub fn hash_subkey_binding<P, Q>(hash: &mut Context, + sig: &signature::SignatureFields, key: &Key<P, key::PrimaryRole>, subkey: &Key<Q, key::SubordinateRole>) - -> Result<Vec<u8>> where P: key::KeyParts, Q: key::KeyParts, { - let mut h = sig.hash_algo().context()?; - - key.hash(&mut h); - subkey.hash(&mut h); - sig.hash(&mut h); - - let mut digest = vec![0u8; h.digest_size()]; - h.digest(&mut digest)?; - Ok(digest) + key.hash(hash); + subkey.hash(hash); + sig.hash(hash); } /// Returns the message digest of the primary key binding over the /// specified primary key and subkey. - pub fn hash_primary_key_binding<P, Q>(sig: &signature::SignatureFields, + pub fn hash_primary_key_binding<P, Q>(hash: &mut Context, + sig: &signature::SignatureFields, key: &Key<P, key::PrimaryRole>, subkey: &Key<Q, key::SubordinateRole>) - -> Result<Vec<u8>> where P: key::KeyParts, Q: key::KeyParts, { - Self::hash_subkey_binding(sig, key, subkey) + Self::hash_subkey_binding(hash, sig, key, subkey); } /// Returns the message digest of the user ID binding over the /// specified primary key, user ID, and signature. - pub fn hash_userid_binding<P>(sig: &signature::SignatureFields, + pub fn hash_userid_binding<P>(hash: &mut Context, + sig: &signature::SignatureFields, key: &Key<P, key::PrimaryRole>, userid: &UserID) - -> Result<Vec<u8>> where P: key::KeyParts, { - let mut h = sig.hash_algo().context()?; - - key.hash(&mut h); - userid.hash(&mut h); - sig.hash(&mut h); - - let mut digest = vec![0u8; h.digest_size()]; - h.digest(&mut digest)?; - Ok(digest) + key.hash(hash); + userid.hash(hash); + sig.hash(hash); } /// Returns the message digest of the user attribute binding over /// the specified primary key, user attribute, and signature. pub fn hash_user_attribute_binding<P>( + hash: &mut Context, sig: &signature::SignatureFields, key: &Key<P, key::PrimaryRole>, ua: &UserAttribute) - -> Result<Vec<u8>> where P: key::KeyParts, { - let mut h = sig.hash_algo().context()?; - - key.hash(&mut h); - ua.hash(&mut h); - sig.hash(&mut h); - - let mut digest = vec![0u8; h.digest_size()]; - h.digest(&mut digest)?; - Ok(digest) + key.hash(hash); + ua.hash(hash); + sig.hash(hash); } } @@ -503,10 +479,13 @@ mod test { let mut userid_sigs = 0; for (i, binding) in cert.userids().enumerate() { for selfsig in binding.self_signatures() { - let h = Signature::hash_userid_binding( + let mut hash = selfsig.hash_algo().context().unwrap(); + Signature::hash_userid_binding( + &mut hash, selfsig, cert.primary_key().key(), - binding.userid()).unwrap(); + binding.userid()); + let h = hash.into_digest().unwrap(); if &h[..2] != selfsig.digest_prefix() { eprintln!("{:?}: {:?} / {:?}", i, binding.userid(), selfsig); @@ -520,10 +499,13 @@ mod test { for (i, a) in cert.user_attributes().enumerate() { for selfsig in a.self_signatures() { - let h = Signature::hash_user_attribute_binding( + let mut hash = selfsig.hash_algo().context().unwrap(); + Signature::hash_user_attribute_binding( + &mut hash, selfsig, cert.primary_key().key(), - a.user_attribute()).unwrap(); + a.user_attribute()); + let h = hash.into_digest().unwrap(); if &h[..2] != selfsig.digest_prefix() { eprintln!("{:?}: {:?} / {:?}", i, a.user_attribute(), selfsig); @@ -536,10 +518,13 @@ mod test { let mut subkey_sigs = 0; for (i, binding) in cert.subkeys().enumerate() { for selfsig in binding.self_signatures() { - let h = Signature::hash_subkey_binding( + let mut hash = selfsig.hash_algo().context().unwrap(); + Signature::hash_subkey_binding( + &mut hash, selfsig, cert.primary_key().key(), - binding.key()).unwrap(); + binding.key()); + let h = hash.into_digest().unwrap(); if &h[..2] != selfsig.digest_prefix() { eprintln!("{:?}: {:?}", i, binding); eprintln!(" Hash: {:?}", h); diff --git a/openpgp/src/packet/signature.rs b/openpgp/src/packet/signature.rs index 07ba1098..e0cf5d37 100644 --- a/openpgp/src/packet/signature.rs +++ b/openpgp/src/packet/signature.rs @@ -577,9 +577,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = Signature::hash_standalone(&self)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_standalone(&mut hash, &self); + self.sign(signer, hash.into_digest()?) } /// Generates a Timestamp Signature. @@ -690,9 +690,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = Signature::hash_timestamp(&self)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_timestamp(&mut hash, &self); + self.sign(signer, hash.into_digest()?) } /// Generates a Direct Key Signature. @@ -813,9 +813,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = Signature::hash_direct_key(&self, pk)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_direct_key(&mut hash, &self, pk); + self.sign(signer, hash.into_digest()?) } /// Generates a User ID binding signature. @@ -950,9 +950,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = Signature::hash_userid_binding(&self, key, userid)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_userid_binding(&mut hash, &self, key, userid); + self.sign(signer, hash.into_digest()?) } /// Generates a subkey binding signature. @@ -1070,9 +1070,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = Signature::hash_subkey_binding(&self, primary, subkey)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_subkey_binding(&mut hash, &self, primary, subkey); + self.sign(signer, hash.into_digest()?) } /// Generates a primary key binding signature. @@ -1218,10 +1218,9 @@ impl SignatureBuilder { self = self.pre_sign(subkey_signer)?; - let digest = - Signature::hash_primary_key_binding(&self, primary, subkey)?; - - self.sign(subkey_signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_primary_key_binding(&mut hash, &self, primary, subkey); + self.sign(subkey_signer, hash.into_digest()?) } @@ -1353,10 +1352,9 @@ impl SignatureBuilder { self = self.pre_sign(signer)?; - let digest = - Signature::hash_user_attribute_binding(&self, key, ua)?; - - self.sign(signer, digest) + let mut hash = self.hash_algo().context()?; + Signature::hash_user_attribute_binding(&mut hash, &self, key, ua); + self.sign(signer, hash.into_digest()?) } /// Generates a signature. @@ -2419,8 +2417,9 @@ impl Signature { // Standalone signatures are like binary-signatures over the // zero-sized string. - let digest = Signature::hash_standalone(self)?; - self.verify_digest(key, &digest[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_standalone(&mut hash, &self); + self.verify_digest(key, &hash.into_digest()?[..]) } /// Verifies the timestamp signature using `key`. @@ -2446,8 +2445,9 @@ impl Signature { // Timestamp signatures are like binary-signatures over the // zero-sized string. - let digest = Signature::hash_timestamp(self)?; - self.verify_digest(key, &digest[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_timestamp(&mut hash, &self); + self.verify_digest(key, &hash.into_digest()?[..]) } /// Verifies the direct key signature. @@ -2481,8 +2481,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_direct_key(self, pk)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_direct_key(&mut hash, &self, pk); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the primary key revocation certificate. @@ -2516,8 +2517,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_direct_key(self, pk)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_direct_key(&mut hash, &self, pk); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the subkey binding. @@ -2559,8 +2561,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_subkey_binding(self, pk, subkey)?; - self.verify_digest(signer, &hash[..])?; + let mut hash = self.hash_algo().context()?; + Signature::hash_subkey_binding(&mut hash, &self, pk, subkey); + self.verify_digest(signer, &hash.into_digest()?[..])?; // The signature is good, but we may still need to verify the // back sig. @@ -2622,8 +2625,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_primary_key_binding(self, pk, subkey)?; - self.verify_digest(subkey, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_primary_key_binding(&mut hash, &self, pk, subkey); + self.verify_digest(subkey, &hash.into_digest()?[..]) } /// Verifies the subkey revocation. @@ -2660,8 +2664,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_subkey_binding(self, pk, subkey)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_subkey_binding(&mut hash, &self, pk, subkey); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the user id binding. @@ -2699,8 +2704,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_userid_binding(self, pk, userid)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_userid_binding(&mut hash, &self, pk, userid); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the user id revocation certificate. @@ -2735,8 +2741,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_userid_binding(self, pk, userid)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_userid_binding(&mut hash, &self, pk, userid); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the user attribute binding. @@ -2774,8 +2781,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_user_attribute_binding(self, pk, ua)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_user_attribute_binding(&mut hash, &self, pk, ua); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies the user attribute revocation certificate. @@ -2811,8 +2819,9 @@ impl Signature { return Err(Error::UnsupportedSignatureType(self.typ()).into()); } - let hash = Signature::hash_user_attribute_binding(self, pk, ua)?; - self.verify_digest(signer, &hash[..]) + let mut hash = self.hash_algo().context()?; + Signature::hash_user_attribute_binding(&mut hash, &self, pk, ua); + self.verify_digest(signer, &hash.into_digest()?[..]) } /// Verifies a signature of a message. @@ -3267,7 +3276,9 @@ mod test { let p = Packet::from_bytes(crate::tests::file( "contrib/gnupg/timestamp-signature-by-alice.asc")).unwrap(); if let Packet::Signature(mut sig) = p { - let digest = Signature::hash_standalone(&sig).unwrap(); + let mut hash = sig.hash_algo().context().unwrap(); + Signature::hash_standalone(&mut hash, &sig); + let digest = hash.into_digest().unwrap(); eprintln!("{}", crate::fmt::hex::encode(&digest)); sig.verify_timestamp(alpha.primary_key().key()).unwrap(); } else { |