summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto/s2k.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/crypto/s2k.rs')
-rw-r--r--openpgp/src/crypto/s2k.rs108
1 files changed, 70 insertions, 38 deletions
diff --git a/openpgp/src/crypto/s2k.rs b/openpgp/src/crypto/s2k.rs
index b99e1a56..84b75b02 100644
--- a/openpgp/src/crypto/s2k.rs
+++ b/openpgp/src/crypto/s2k.rs
@@ -76,10 +76,39 @@ pub enum S2K {
hash: HashAlgorithm
},
- /// Private S2K algorithm
- Private(u8),
- /// Unknown S2K algorithm
- Unknown(u8),
+ /// Private S2K algorithm.
+ Private {
+ /// Tag identifying the private algorithm.
+ ///
+ /// Tags 100 to 110 are reserved for private use.
+ tag: u8,
+
+ /// The parameters for the private algorithm.
+ ///
+ /// This is optional, because when we parse a packet
+ /// containing an unknown S2K algorithm, we do not know how
+ /// many octets to attribute to the S2K's parameters. In this
+ /// case, `parameters` is set to `None`. Note that the
+ /// information is not lost, but stored in the packet. If the
+ /// packet is serialized again, it is written out.
+ parameters: Option<Box<[u8]>>,
+ },
+
+ /// Unknown S2K algorithm.
+ Unknown {
+ /// Tag identifying the unknown algorithm.
+ tag: u8,
+
+ /// The parameters for the unknown algorithm.
+ ///
+ /// This is optional, because when we parse a packet
+ /// containing an unknown S2K algorithm, we do not know how
+ /// many octets to attribute to the S2K's parameters. In this
+ /// case, `parameters` is set to `None`. Note that the
+ /// information is not lost, but stored in the packet. If the
+ /// packet is serialized again, it is written out.
+ parameters: Option<Box<[u8]>>,
+ },
/// This marks this enum as non-exhaustive. Do not use this
/// variant.
@@ -196,7 +225,8 @@ impl S2K {
hash.update(&data[0..tail]);
}
}
- &S2K::Unknown(_) | &S2K::Private(_) => unreachable!(),
+ S2K::Unknown { .. } | &S2K::Private { .. } =>
+ unreachable!(),
S2K::__Nonexhaustive => unreachable!(),
}
@@ -206,9 +236,9 @@ impl S2K {
Ok(ret.into())
}),
- &S2K::Unknown(u) | &S2K::Private(u) =>
+ S2K::Unknown { tag, .. } | S2K::Private { tag, .. } =>
Err(Error::MalformedPacket(
- format!("Unknown S2K type {:#x}", u)).into()),
+ format!("Unknown S2K type {:#x}", tag)).into()),
S2K::__Nonexhaustive => unreachable!(),
}
}
@@ -323,9 +353,18 @@ impl fmt::Display for S2K {
salt[4], salt[5], salt[6], salt[7],
hash_bytes))
}
- S2K::Private(u) =>
- f.write_fmt(format_args!("Private/Experimental S2K {}", u)),
- S2K::Unknown(u) => f.write_fmt(format_args!("Unknown S2K {}", u)),
+ S2K::Private { tag, parameters } =>
+ if let Some(p) = parameters.as_ref() {
+ write!(f, "Private/Experimental S2K {}:{:?}", tag, p)
+ } else {
+ write!(f, "Private/Experimental S2K {}", tag)
+ },
+ S2K::Unknown { tag, parameters } =>
+ if let Some(p) = parameters.as_ref() {
+ write!(f, "Unknown S2K {}:{:?}", tag, p)
+ } else {
+ write!(f, "Unknown S2K {}", tag)
+ },
S2K::__Nonexhaustive => unreachable!(),
}
}
@@ -335,7 +374,7 @@ impl fmt::Display for S2K {
impl Arbitrary for S2K {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
#[allow(deprecated)]
- match g.gen_range(0, 5) {
+ match g.gen_range(0, 7) {
0 => S2K::Simple{ hash: HashAlgorithm::arbitrary(g) },
1 => S2K::Salted{
hash: HashAlgorithm::arbitrary(g),
@@ -346,8 +385,22 @@ impl Arbitrary for S2K {
salt: g.gen(),
hash_bytes: S2K::nearest_hash_count(g.gen()),
},
- 3 => S2K::Private(g.gen_range(100, 111)),
- 4 => S2K::Unknown(g.gen_range(4, 100)),
+ 3 => S2K::Private {
+ tag: g.gen_range(100, 111),
+ parameters: Option::<Vec<u8>>::arbitrary(g).map(|v| v.into()),
+ },
+ 4 => S2K::Unknown {
+ tag: 2,
+ parameters: Option::<Vec<u8>>::arbitrary(g).map(|v| v.into()),
+ },
+ 5 => S2K::Unknown {
+ tag: g.gen_range(4, 100),
+ parameters: Option::<Vec<u8>>::arbitrary(g).map(|v| v.into()),
+ },
+ 6 => S2K::Unknown {
+ tag: g.gen_range(111, 256) as u8,
+ parameters: Option::<Vec<u8>>::arbitrary(g).map(|v| v.into()),
+ },
_ => unreachable!(),
}
}
@@ -493,29 +546,6 @@ mod tests {
}
quickcheck! {
- fn s2k_roundtrip(s2k: S2K) -> bool {
- use crate::serialize::Marshal;
- use crate::serialize::MarshalInto;
-
- eprintln!("in {:?}", s2k);
- use std::io::Cursor;
-
- let mut w = Cursor::new(Vec::new());
- let l = s2k.serialized_len();
- s2k.serialize(&mut w).unwrap();
- let buf = w.into_inner();
- eprintln!("raw: {:?}", buf);
-
- assert_eq!(buf.len(), l);
- let mut r = Cursor::new(buf.into_boxed_slice());
- let s = S2K::from_reader(&mut r).unwrap();
- eprintln!("out {:?}", s);
-
- s2k == s
- }
- }
-
- quickcheck! {
fn s2k_display(s2k: S2K) -> bool {
let s = format!("{}", s2k);
!s.is_empty()
@@ -525,8 +555,10 @@ mod tests {
quickcheck! {
fn s2k_parse(s2k: S2K) -> bool {
match s2k {
- S2K::Unknown(u) => (u > 3 && u < 100) || u == 2 || u > 110,
- S2K::Private(u) => u >= 100 && u <= 110,
+ S2K::Unknown { tag, .. } =>
+ (tag > 3 && tag < 100) || tag == 2 || tag > 110,
+ S2K::Private { tag, .. } =>
+ tag >= 100 && tag <= 110,
_ => true
}
}