diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-06-28 13:59:48 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-06-28 13:59:48 +0200 |
commit | 1525eec1426a6a34b84809179d784e5cee3e8bfa (patch) | |
tree | 1e73534e95d14f776085df7ca6154057b8108712 | |
parent | f214d55b7061e9d6006f915ee8fbedf29ddf6078 (diff) |
openpgp: Make struct MPI opaque.
-rw-r--r-- | openpgp/src/crypto/asymmetric.rs | 30 | ||||
-rw-r--r-- | openpgp/src/crypto/ecdh.rs | 10 | ||||
-rw-r--r-- | openpgp/src/crypto/keygrip.rs | 12 | ||||
-rw-r--r-- | openpgp/src/crypto/mpis.rs | 14 | ||||
-rw-r--r-- | openpgp/src/crypto/sexp.rs | 8 | ||||
-rw-r--r-- | openpgp/src/packet/key.rs | 3 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 26 | ||||
-rw-r--r-- | openpgp/src/parse/mpis.rs | 20 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 29 | ||||
-rw-r--r-- | openpgp/src/serialize/mod.rs | 6 | ||||
-rw-r--r-- | tool/src/commands/dump.rs | 68 |
12 files changed, 122 insertions, 108 deletions
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs index 839f0eaa..050d83a9 100644 --- a/openpgp/src/crypto/asymmetric.rs +++ b/openpgp/src/crypto/asymmetric.rs @@ -97,12 +97,12 @@ impl Signer for KeyPair { (RSAEncryptSign, &PublicKey::RSA { ref e, ref n }, &mpis::SecretKey::RSA { ref p, ref q, ref d, .. }) => { - let public = rsa::PublicKey::new(&n.value, &e.value)?; - let secret = rsa::PrivateKey::new(&d.value, &p.value, - &q.value, Option::None)?; + let public = rsa::PublicKey::new(n.value(), e.value())?; + let secret = rsa::PrivateKey::new(d.value(), p.value(), + q.value(), Option::None)?; // The signature has the length of the modulus. - let mut sig = vec![0u8; n.value.len()]; + let mut sig = vec![0u8; n.value().len()]; // As described in [Section 5.2.2 and 5.2.3 of RFC 4880], // to verify the signature, we need to encode the @@ -122,8 +122,8 @@ impl Signer for KeyPair { (DSA, &PublicKey::DSA { ref p, ref q, ref g, .. }, &mpis::SecretKey::DSA { ref x }) => { - let params = dsa::Params::new(&p.value, &q.value, &g.value); - let secret = dsa::PrivateKey::new(&x.value); + let params = dsa::Params::new(p.value(), q.value(), g.value()); + let secret = dsa::PrivateKey::new(x.value()); let sig = dsa::sign(¶ms, &secret, digest, &mut rng)?; @@ -147,9 +147,9 @@ impl Signer for KeyPair { // Padding has to be unconditionaly, otherwise we have a // secret-dependant branch. let missing = ed25519::ED25519_KEY_SIZE - .saturating_sub(scalar.value.len()); + .saturating_sub(scalar.value().len()); let mut sec = [0u8; ed25519::ED25519_KEY_SIZE]; - sec[missing..].copy_from_slice(&scalar.value[..]); + sec[missing..].copy_from_slice(scalar.value()); let res = ed25519::sign(public, &sec[..], digest, &mut sig); unsafe { @@ -173,13 +173,13 @@ impl Signer for KeyPair { let secret = match curve { Curve::NistP256 => ecc::Scalar::new::<ecc::Secp256r1>( - &scalar.value)?, + scalar.value())?, Curve::NistP384 => ecc::Scalar::new::<ecc::Secp384r1>( - &scalar.value)?, + scalar.value())?, Curve::NistP521 => ecc::Scalar::new::<ecc::Secp521r1>( - &scalar.value)?, + scalar.value())?, _ => return Err( Error::UnsupportedEllipticCurve(curve.clone()) @@ -220,11 +220,11 @@ impl Decryptor for KeyPair { (PublicKey::RSA{ ref e, ref n }, mpis::SecretKey::RSA{ ref p, ref q, ref d, .. }, mpis::Ciphertext::RSA{ ref c }) => { - let public = rsa::PublicKey::new(&n.value, &e.value)?; - let secret = rsa::PrivateKey::new(&d.value, &p.value, - &q.value, Option::None)?; + let public = rsa::PublicKey::new(n.value(), e.value())?; + let secret = rsa::PrivateKey::new(d.value(), p.value(), + q.value(), Option::None)?; let mut rand = Yarrow::default(); - rsa::decrypt_pkcs1(&public, &secret, &mut rand, &c.value)? + rsa::decrypt_pkcs1(&public, &secret, &mut rand, c.value())? .into() } diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs index 3f0fb590..d8ba73f3 100644 --- a/openpgp/src/crypto/ecdh.rs +++ b/openpgp/src/crypto/ecdh.rs @@ -183,10 +183,10 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey, // Reverse the scalar. See // https://lists.gnupg.org/pipermail/gnupg-devel/2018-February/033437.html. let missing = curve25519::CURVE25519_SIZE - .saturating_sub(scalar.value.len()); + .saturating_sub(scalar.value().len()); let mut r = [0u8; curve25519::CURVE25519_SIZE]; - r[missing..].copy_from_slice(&scalar.value[..]); + r[missing..].copy_from_slice(scalar.value()); r.reverse(); // Compute the shared point S = rV = rvG, where (r, R) @@ -213,7 +213,7 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey, let V = ecc::Point::new::<ecc::Secp256r1>(&Vx, &Vy)?; let r = - ecc::Scalar::new::<ecc::Secp256r1>(&scalar.value[..])?; + ecc::Scalar::new::<ecc::Secp256r1>(scalar.value())?; (V, r) } @@ -221,7 +221,7 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey, let V = ecc::Point::new::<ecc::Secp384r1>(&Vx, &Vy)?; let r = - ecc::Scalar::new::<ecc::Secp384r1>(&scalar.value[..])?; + ecc::Scalar::new::<ecc::Secp384r1>(scalar.value())?; (V, r) } @@ -229,7 +229,7 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey, let V = ecc::Point::new::<ecc::Secp521r1>(&Vx, &Vy)?; let r = - ecc::Scalar::new::<ecc::Secp521r1>(&scalar.value[..])?; + ecc::Scalar::new::<ecc::Secp521r1>(scalar.value())?; (V, r) } diff --git a/openpgp/src/crypto/keygrip.rs b/openpgp/src/crypto/keygrip.rs index feccebc4..a9f3cd0a 100644 --- a/openpgp/src/crypto/keygrip.rs +++ b/openpgp/src/crypto/keygrip.rs @@ -57,9 +57,9 @@ impl PublicKey { where H: Hash + ::std::io::Write { write!(hash, "(1:{}{}:", - kind, mpi.value.len() + prefix.len()).unwrap(); + kind, mpi.value().len() + prefix.len()).unwrap(); hash.update(prefix); - hash.update(&mpi.value); + hash.update(mpi.value()); write!(hash, ")").unwrap(); } @@ -75,11 +75,11 @@ impl PublicKey { if i == 6 { q.clone() } else { ecc_param(curve, i) }; // Opaque encoding? - if m.value[0] == 0x40 { + if m.value()[0] == 0x40 { // Drop the prefix! - let mut p = Vec::from(m.value); + let mut p = Vec::from(m.value()); p.remove(0); - m.value = p.into(); + m = p.into(); } hash_sexp_mpi(hash, name, &[], &m); @@ -99,7 +99,7 @@ impl PublicKey { // overwhelming empirical evidence suggest that we // need to prepend a 0. hash.update(&[0]); - hash.update(&n.value); + hash.update(n.value()); }, &DSA { ref p, ref q, ref g, ref y } => { diff --git a/openpgp/src/crypto/mpis.rs b/openpgp/src/crypto/mpis.rs index d93223ca..c1871619 100644 --- a/openpgp/src/crypto/mpis.rs +++ b/openpgp/src/crypto/mpis.rs @@ -23,9 +23,9 @@ use nettle; #[derive(Clone, Hash)] pub struct MPI { /// Length of the integer in bits. - pub bits: usize, + bits: usize, /// Integer value as big-endian. - pub value: Box<[u8]>, + value: Box<[u8]>, } impl From<Vec<u8>> for MPI { @@ -73,6 +73,16 @@ impl MPI { } } + /// Returns the length of the MPI in bits. + pub fn bits(&self) -> usize { + self.bits + } + + /// Returns the value of this MPI. + pub fn value(&self) -> &[u8] { + &self.value + } + /// Update the Hash with a hash of the MPIs. pub fn hash<H: nettle::Hash>(&self, hash: &mut H) { let len = &[(self.bits >> 8) as u8 & 0xFF, self.bits as u8]; diff --git a/openpgp/src/crypto/sexp.rs b/openpgp/src/crypto/sexp.rs index 04fefd27..8bd958a6 100644 --- a/openpgp/src/crypto/sexp.rs +++ b/openpgp/src/crypto/sexp.rs @@ -51,7 +51,7 @@ impl Sexp { Sexp::String("rsa".into()), Sexp::List(vec![ Sexp::String("a".into()), - Sexp::String(c.value.as_ref().into())])])])), + Sexp::String(c.value().into())])])])), &Elgamal { ref e, ref c } => Ok(Sexp::List(vec![ @@ -60,10 +60,10 @@ impl Sexp { Sexp::String("elg".into()), Sexp::List(vec![ Sexp::String("a".into()), - Sexp::String(e.value.as_ref().into())]), + Sexp::String(e.value().into())]), Sexp::List(vec![ Sexp::String("b".into()), - Sexp::String(c.value.as_ref().into())])])])), + Sexp::String(c.value().into())])])])), &ECDH { ref e, ref key } => Ok(Sexp::List(vec![ @@ -75,7 +75,7 @@ impl Sexp { Sexp::String(key.as_ref().into())]), Sexp::List(vec![ Sexp::String("e".into()), - Sexp::String(e.value.as_ref().into())])])])), + Sexp::String(e.value().into())])])])), &Unknown { .. } => Err(Error::InvalidArgument( diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index bf687b81..62ccbb22 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -941,7 +941,8 @@ mod tests { SymmetricAlgorithm::AES128, ctime).unwrap().into(); match key.mpis { - self::mpis::PublicKey::ECDH{ ref q,.. } => assert_eq!(&q.value[1..], &public[..]), + self::mpis::PublicKey::ECDH{ ref q,.. } => + assert_eq!(&q.value()[1..], &public[..]), _ => unreachable!(), } diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index 1088d848..012c940e 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -82,9 +82,9 @@ impl PKESK3 { match recipient.mpis() { &mpis::PublicKey::RSA { ref e, ref n } => { // The ciphertext has the length of the modulus. - let mut esk = vec![0u8; n.value.len()]; + let mut esk = vec![0u8; n.value().len()]; - let pk = rsa::PublicKey::new(&n.value, &e.value)?; + let pk = rsa::PublicKey::new(n.value(), e.value())?; rsa::encrypt_pkcs1(&pk, &mut rng, &psk, &mut esk)?; Ciphertext::RSA {c: MPI::new(&esk)} } diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index c08046f4..04bb81e9 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -476,7 +476,7 @@ impl Signature4 { (RSAEncryptSign, &PublicKey::RSA{ ref e, ref n }, &mpis::Signature::RSA { ref s }) => { - let key = rsa::PublicKey::new(&n.value, &e.value)?; + let key = rsa::PublicKey::new(n.value(), e.value())?; // As described in [Section 5.2.2 and 5.2.3 of RFC 4880], // to verify the signature, we need to encode the @@ -484,15 +484,15 @@ impl Signature4 { // // [Section 5.2.2 and 5.2.3 of RFC 4880]: // https://tools.ietf.org/html/rfc4880#section-5.2.2 - verify_digest_pkcs1(&key, hash, hash_algo.oid()?, &s.value) + verify_digest_pkcs1(&key, hash, hash_algo.oid()?, s.value()) } (DSA, &PublicKey::DSA{ ref y, ref p, ref q, ref g }, &mpis::Signature::DSA { ref s, ref r }) => { - let key = dsa::PublicKey::new(&y.value); - let params = dsa::Params::new(&p.value, &q.value, &g.value); - let signature = dsa::Signature::new(&r.value, &s.value); + let key = dsa::PublicKey::new(y.value()); + let params = dsa::Params::new(p.value(), q.value(), g.value()); + let signature = dsa::Signature::new(r.value(), s.value()); Ok(dsa::verify(¶ms, &key, hash, &signature)) } @@ -501,7 +501,7 @@ impl Signature4 { &PublicKey::EdDSA{ ref curve, ref q }, &mpis::Signature::EdDSA { ref r, ref s }) => match curve { Curve::Ed25519 => { - if q.value[0] != 0x40 { + if q.value().get(0).map(|&b| b != 0x40).unwrap_or(true) { return Err(Error::MalformedPacket( "Invalid point encoding".into()).into()); } @@ -515,24 +515,24 @@ impl Signature4 { // We need to zero-pad them at the front, because // the MPI encoding drops leading zero bytes. let half = ed25519::ED25519_SIGNATURE_SIZE / 2; - for _ in 0..half - r.value.len() { + for _ in 0..half - r.value().len() { signature.push(0); } - signature.extend_from_slice(&r.value); - for _ in 0..half - s.value.len() { + signature.extend_from_slice(r.value()); + for _ in 0..half - s.value().len() { signature.push(0); } - signature.extend_from_slice(&s.value); + signature.extend_from_slice(s.value()); // Let's see if we got it right. if signature.len() != ed25519::ED25519_SIGNATURE_SIZE { return Err(Error::MalformedPacket( format!( "Invalid signature size: {}, r: {:?}, s: {:?}", - signature.len(), &r.value, &s.value)).into()); + signature.len(), r.value(), s.value())).into()); } - ed25519::verify(&q.value[1..], hash, &signature) + ed25519::verify(&q.value()[1..], hash, &signature) }, _ => Err(Error::UnsupportedEllipticCurve(curve.clone()) @@ -556,7 +556,7 @@ impl Signature4 { .into()), }; - let signature = dsa::Signature::new(&r.value, &s.value); + let signature = dsa::Signature::new(r.value(), s.value()); Ok(ecdsa::verify(&key, hash, &signature)) }, diff --git a/openpgp/src/parse/mpis.rs b/openpgp/src/parse/mpis.rs index 49c7e5f4..3b78755b 100644 --- a/openpgp/src/parse/mpis.rs +++ b/openpgp/src/parse/mpis.rs @@ -478,12 +478,12 @@ fn mpis_parse_test() { //assert_eq!(mpis.serialized_len(), 6); match &mpis { &mpis::PublicKey::RSA{ ref n, ref e } => { - assert_eq!(n.bits, 1); - assert_eq!(n.value[0], 1); - assert_eq!(n.value.len(), 1); - assert_eq!(e.bits, 2); - assert_eq!(e.value[0], 2); - assert_eq!(e.value.len(), 1); + assert_eq!(n.bits(), 1); + assert_eq!(n.value()[0], 1); + assert_eq!(n.value().len(), 1); + assert_eq!(e.bits(), 2); + assert_eq!(e.value()[0], 2); + assert_eq!(e.value().len(), 1); } _ => assert!(false), @@ -500,10 +500,10 @@ fn mpis_parse_test() { // The number 511. let mpi = MPI::from_bytes(b"\x00\x09\x01\xff").unwrap(); - assert_eq!(mpi.value.len(), 2); - assert_eq!(mpi.bits, 9); - assert_eq!(mpi.value[0], 1); - assert_eq!(mpi.value[1], 0xff); + assert_eq!(mpi.value().len(), 2); + assert_eq!(mpi.bits(), 9); + assert_eq!(mpi.value()[0], 1); + assert_eq!(mpi.value()[1], 0xff); // The number 1, incorrectly encoded (the length should be 1, // not 2). diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index 8df103e8..5ff6d599 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -1961,7 +1961,7 @@ impl MPI { if bits == 0 { // Now consume the data. php.parse_be_u16(name_len).expect("worked before"); - return Ok(MPI{ bits: 0, value: vec![].into_boxed_slice()}); + return Ok(vec![].into()); } let bytes = (bits + 7) / 8; @@ -1996,10 +1996,7 @@ impl MPI { // Now consume the data. php.parse_be_u16(name_len).expect("worked before"); php.parse_bytes(name, bytes).expect("worked before"); - Ok(MPI{ - bits: bits, - value: value.into_boxed_slice() - }) + Ok(value.into()) } /// Dissects this MPI describing a point into the individual @@ -2019,19 +2016,19 @@ impl MPI { ed25519::ED25519_KEY_SIZE); // This curve uses a custom compression format which // only contains the X coordinate. - if self.value.len() != 1 + curve25519::CURVE25519_SIZE { + if self.value().len() != 1 + curve25519::CURVE25519_SIZE { return Err(Error::MalformedPacket( format!("Bad size of Curve25519 key: {} expected: {}", - self.value.len(), + self.value().len(), 1 + curve25519::CURVE25519_SIZE)).into()); } - if self.value[0] != 0x40 { + if self.value().get(0).map(|&b| b != 0x40).unwrap_or(true) { return Err(Error::MalformedPacket( "Bad encoding of Curve25519 key".into()).into()); } - Ok((&self.value[1..], &[])) + Ok((&self.value()[1..], &[])) }, _ => { @@ -2045,20 +2042,20 @@ impl MPI { + (2 // (x, y) * coordinate_length); - if self.value.len() != expected_length { + if self.value().len() != expected_length { return Err(Error::InvalidArgument( format!("Invalid length of MPI: {} (expected {})", - self.value.len(), expected_length)).into()); + self.value().len(), expected_length)).into()); } - if self.value[0] != 0x04 { + if self.value().get(0).map(|&b| b != 0x04).unwrap_or(true) { return Err(Error::InvalidArgument( - format!("Bad prefix: {:x} (expected 0x04)", self.value[0])) - .into()); + format!("Bad prefix: {:?} (expected Some(0x04))", + self.value().get(0))).into()); } - Ok((&self.value[1..1 + coordinate_length], - &self.value[1 + coordinate_length..])) + Ok((&self.value()[1..1 + coordinate_length], + &self.value()[1 + coordinate_length..])) }, } } diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index 66a2017d..454a484d 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -407,15 +407,15 @@ impl SerializeInto for Fingerprint { impl Serialize for crypto::mpis::MPI { fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> { - write_be_u16(w, self.bits as u16)?; - w.write_all(&self.value)?; + write_be_u16(w, self.bits() as u16)?; + w.write_all(self.value())?; Ok(()) } } impl SerializeInto for crypto::mpis::MPI { fn serialized_len(&self) -> usize { - 2 + self.value.len() + 2 + self.value().len() } fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> { diff --git a/tool/src/commands/dump.rs b/tool/src/commands/dump.rs index 57ee8deb..1ddef539 100644 --- a/tool/src/commands/dump.rs +++ b/tool/src/commands/dump.rs @@ -255,23 +255,23 @@ impl PacketDumper { match s.mpis() { RSA { s } => self.dump_mpis(output, &ii, - &[&s.value], + &[s.value()], &["s"])?, DSA { r, s } => self.dump_mpis(output, &ii, - &[&r.value, &s.value], + &[r.value(), s.value()], &["r", "s"])?, Elgamal { r, s } => self.dump_mpis(output, &ii, - &[&r.value, &s.value], + &[r.value(), s.value()], &["r", "s"])?, EdDSA { r, s } => self.dump_mpis(output, &ii, - &[&r.value, &s.value], + &[r.value(), s.value()], &["r", "s"])?, ECDSA { r, s } => self.dump_mpis(output, &ii, - &[&r.value, &s.value], + &[r.value(), s.value()], &["r", "s"])?, Unknown { mpis, rest } => { let keys: Vec<String> = @@ -279,8 +279,9 @@ impl PacketDumper { |i| format!("mpi{}", i)).collect(); self.dump_mpis( output, &ii, - &mpis.iter().map(|m| m.value.iter().as_slice()) - .collect::<Vec<_>>()[..], + &mpis.iter().map(|m| { + m.value().iter().as_slice() + }).collect::<Vec<_>>()[..], &keys.iter().map(|k| k.as_str()) .collect::<Vec<_>>()[..], )?; @@ -321,31 +322,31 @@ impl PacketDumper { match k.mpis() { RSA { e, n } => self.dump_mpis(output, &ii, - &[&e.value, &n.value], + &[e.value(), n.value()], &["e", "n"])?, DSA { p, q, g, y } => self.dump_mpis(output, &ii, - &[&p.value, &q.value, &g.value, - &y.value], + &[p.value(), q.value(), g.value(), + y.value()], &["p", "q", "g", "y"])?, Elgamal { p, g, y } => self.dump_mpis(output, &ii, - &[&p.value, &g.value, &y.value], + &[p.value(), g.value(), y.value()], &["p", "g", "y"])?, EdDSA { curve, q } => { writeln!(output, "{} Curve: {}", ii, curve)?; - self.dump_mpis(output, &ii, &[&q.value], &["q"])?; + self.dump_mpis(output, &ii, &[q.value()], &["q"])?; }, ECDSA { curve, q } => { writeln!(output, "{} Curve: {}", ii, curve)?; - self.dump_mpis(output, &ii, &[&q.value], &["q"])?; + self.dump_mpis(output, &ii, &[q.value()], &["q"])?; }, ECDH { curve, q, hash, sym } => { writeln!(output, "{} Curve: {}", ii, curve)?; writeln!(output, "{} Hash algo: {}", ii, hash)?; writeln!(output, "{} Symmetric algo: {}", ii, sym)?; - self.dump_mpis(output, &ii, &[&q.value], &["q"])?; + self.dump_mpis(output, &ii, &[q.value()], &["q"])?; }, Unknown { mpis, rest } => { let keys: Vec<String> = @@ -353,8 +354,9 @@ impl PacketDumper { |i| format!("mpi{}", i)).collect(); self.dump_mpis( output, &ii, - &mpis.iter().map(|m| m.value.iter().as_slice()) - .collect::<Vec<_>>()[..], + &mpis.iter().map(|m| { + m.value().iter().as_slice() + }).collect::<Vec<_>>()[..], &keys.iter().map(|k| k.as_str()) .collect::<Vec<_> |