summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-01-03 12:38:49 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-01-03 12:38:49 +0100
commit7fd9f46fcc4ffb863b02e493fcbe49295564b741 (patch)
treea86b8710739a873a5ae02ecc4e636567d60b4eca /openpgp/src/crypto
parentab726285b21cb5b342e14507ef9177f3dcdde775 (diff)
openpgp: Explicitly implement Eq and Hash if PartialEq is.
- If we don't derive PartialEq, then deriving hash is unsafe. - See #92.
Diffstat (limited to 'openpgp/src/crypto')
-rw-r--r--openpgp/src/crypto/mem.rs11
-rw-r--r--openpgp/src/crypto/mpis.rs18
2 files changed, 26 insertions, 3 deletions
diff --git a/openpgp/src/crypto/mem.rs b/openpgp/src/crypto/mem.rs
index a67cf993..4dfe5457 100644
--- a/openpgp/src/crypto/mem.rs
+++ b/openpgp/src/crypto/mem.rs
@@ -2,6 +2,7 @@
use std::cmp::{min, Ordering};
use std::fmt;
+use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
@@ -11,7 +12,7 @@ use memsec;
///
/// The memory is guaranteed not to be copied around, and is cleared
/// when the object is dropped.
-#[derive(Clone, Eq, Hash)]
+#[derive(Clone)]
pub struct Protected(Pin<Box<[u8]>>);
impl PartialEq for Protected {
@@ -20,6 +21,14 @@ impl PartialEq for Protected {
}
}
+impl Eq for Protected {}
+
+impl Hash for Protected {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+}
+
impl Protected {
/// Converts to a buffer for modification.
pub unsafe fn into_vec(self) -> Vec<u8> {
diff --git a/openpgp/src/crypto/mpis.rs b/openpgp/src/crypto/mpis.rs
index 37f75213..4460cc58 100644
--- a/openpgp/src/crypto/mpis.rs
+++ b/openpgp/src/crypto/mpis.rs
@@ -20,7 +20,7 @@ use crate::Error;
use crate::Result;
/// Holds a single MPI.
-#[derive(Clone, Hash)]
+#[derive(Clone)]
pub struct MPI {
/// Integer value as big-endian.
value: Box<[u8]>,
@@ -216,10 +216,16 @@ impl PartialEq for MPI {
impl Eq for MPI {}
+impl std::hash::Hash for MPI {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.value.hash(state);
+ }
+}
+
/// Holds a single MPI containing secrets.
///
/// The memory will be cleared when the object is dropped.
-#[derive(Clone, Hash)]
+#[derive(Clone)]
pub struct ProtectedMPI {
/// Integer value as big-endian.
value: Protected,
@@ -245,6 +251,12 @@ impl From<MPI> for ProtectedMPI {
}
}
+impl std::hash::Hash for ProtectedMPI {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.value.hash(state);
+ }
+}
+
impl ProtectedMPI {
/// Returns the length of the MPI in bits.
pub fn bits(&self) -> usize {
@@ -481,6 +493,8 @@ impl Arbitrary for PublicKey {
///
/// Provides a typed and structured way of storing multiple MPIs in
/// packets.
+// Deriving Hash here is okay: PartialEq is manually implemented to
+// ensure that secrets are compared in constant-time.
#[derive(Clone, Hash)]
pub enum SecretKeyMaterial {
/// RSA secret key.