diff options
Diffstat (limited to 'ipc/src/sexp.rs')
-rw-r--r-- | ipc/src/sexp.rs | 72 |
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 { |