summaryrefslogtreecommitdiffstats
path: root/ipc/src/sexp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/src/sexp.rs')
-rw-r--r--ipc/src/sexp.rs72
1 files changed, 52 insertions, 20 deletions
diff --git a/ipc/src/sexp.rs b/ipc/src/sexp.rs
index 8386a827..7a8ce18c 100644
--- a/ipc/src/sexp.rs
+++ b/ipc/src/sexp.rs
@@ -64,11 +64,11 @@ impl Sexp {
};
let value = self.get(b"value")?.ok_or_else(not_a_session_key)?
- .into_iter().nth(0).ok_or_else(not_a_session_key)?;
+ .into_iter().next().ok_or_else(not_a_session_key)?;
match value {
- Sexp::String(ref s) => match recipient.mpis() {
- PublicKey::RSA { .. } | PublicKey::ElGamal { .. } if padding =>
+ Sexp::String(s) => match recipient.mpis() {
+ PublicKey::RSA { .. } | PublicKey::ElGamal { .. } => if padding
{
// The session key is padded. The format is
// described in g10/pubkey-enc.c (note that we,
@@ -81,7 +81,8 @@ impl Sexp {
// * (mpi_get_buffer already removed the leading zero).
// *
// * RND are non-zero random bytes.
- let mut s = &s[..];
+ let s_ = s.into_protected();
+ let mut s = &s_[..];
// The leading 0 may or may not be swallowed along
// the way due to MPI encoding.
@@ -97,11 +98,11 @@ impl Sexp {
}
// Skip non-zero bytes.
- while s.len() > 0 && s[0] > 0 {
+ while !s.is_empty() && s[0] > 0 {
s = &s[1..];
}
- if s.len() == 0 {
+ if s.is_empty() {
return Err(Error::MalformedMPI(
"Invalid DEK encoding, no zero found".into())
.into());
@@ -111,32 +112,30 @@ impl Sexp {
s = &s[1..];
Ok(s.to_vec().into())
- },
-
- PublicKey::RSA { .. } | PublicKey::ElGamal { .. } => {
+ } else {
// The session key is not padded. Currently, this
// happens if the session key is decrypted using
// scdaemon.
- assert!(! padding); // XXX: Don't assert that.
- Ok(s.to_vec().into())
+ Ok(s.into_protected().into())
},
PublicKey::ECDH { curve, .. } => {
// The shared point has been computed by the
// remote agent. The shared point is not padded.
- let s_: mpi::ProtectedMPI = s.to_vec().into();
+ let s_: mpi::ProtectedMPI = s.into_protected().into();
#[allow(non_snake_case)]
let S: Protected = s_.decode_point(curve)?.0.into();
- // XXX: Erase shared point from s.
// Now finish the decryption.
openpgp::crypto::ecdh::decrypt_unwrap(recipient, &S, ciphertext)
},
- _ =>
+ _ => {
+ let _ = s.into_protected();
Err(Error::InvalidArgument(
format!("Don't know how to handle key {:?}", recipient))
- .into()),
+ .into())
+ },
}
Sexp::List(..) => Err(not_a_session_key()),
}
@@ -153,7 +152,7 @@ impl Sexp {
};
let sig = self.get(b"sig-val")?.ok_or_else(not_a_signature)?
- .into_iter().nth(0).ok_or_else(not_a_signature)?;
+ .into_iter().next().ok_or_else(not_a_signature)?;
if let Some(param) = sig.get(b"eddsa")? {
let r = param.iter().find_map(|p| {
@@ -224,7 +223,7 @@ impl Sexp {
}
}
-
+ /// Writes a serialized version of the object to `o`.
pub fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
Sexp::String(ref s) => s.serialize(o),
@@ -245,7 +244,7 @@ impl Sexp {
Sexp::List(ref ll) => match ll.get(0) {
Some(Sexp::String(ref tag)) =>
if tag.deref() == key {
- Ok(Some(ll[1..].iter().cloned().collect()))
+ Ok(Some(ll[1..].to_vec()))
} else {
Ok(None)
}
@@ -315,7 +314,7 @@ impl TryFrom<&mpi::Ciphertext> for Sexp {
#[cfg(test)]
impl Arbitrary for Sexp {
- fn arbitrary<G: Gen>(g: &mut G) -> Self {
+ fn arbitrary(g: &mut Gen) -> Self {
if f32::arbitrary(g) < 0.7 {
Sexp::String(String_::arbitrary(g))
} else {
@@ -382,6 +381,7 @@ impl String_ {
self.1.as_ref().map(|b| b.as_ref())
}
+ /// Writes a serialized version of the object to `o`.
pub fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
if let Some(display) = self.display_hint() {
write!(o, "[{}:", display.len())?;
@@ -392,6 +392,26 @@ impl String_ {
o.write_all(self)?;
Ok(())
}
+
+ /// Creates a Protected memory region from this String.
+ ///
+ /// Securely erases the contents of the original String.
+ pub fn into_protected(self) -> Protected {
+ let r = Protected::from(&self.0[..]);
+ drop(self); // Securely erases this string.
+ r
+ }
+}
+
+impl Drop for String_ {
+ fn drop(&mut self) {
+ unsafe {
+ memsec::memzero(self.0.as_mut_ptr(), self.0.len());
+ if let Some(p) = self.1.as_mut() {
+ memsec::memzero(p.as_mut_ptr(), p.len());
+ }
+ }
+ }
}
impl From<&str> for String_ {
@@ -414,9 +434,21 @@ impl Deref for String_ {
}
}
+impl From<String_> for Sexp {
+ fn from(v: String_) -> Sexp {
+ Sexp::String(v)
+ }
+}
+
+impl From<Vec<Sexp>> for Sexp {
+ fn from(v: Vec<Sexp>) -> Sexp {
+ Sexp::List(v)
+ }
+}
+
#[cfg(test)]
impl Arbitrary for String_ {
- fn arbitrary<G: Gen>(g: &mut G) -> Self {
+ fn arbitrary(g: &mut Gen) -> Self {
if bool::arbitrary(g) {
Self::new(Vec::arbitrary(g).into_boxed_slice())
} else {