use {der, error};
use untrusted;
pub enum Version {
#[cfg(feature = "rsa_signing")] V1Only,
V1OrV2,
V2Only,
}
pub fn unwrap_key<'a>(version: Version, input: untrusted::Input<'a>,
alg_id: &[u8])
-> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>),
error::Unspecified> {
input.read_all(error::Unspecified, |input| {
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
let require_public_key =
match (try!(der::small_nonnegative_integer(input)), version) {
#[cfg(feature = "rsa_signing")] (0, Version::V1Only) => false,
(0, Version::V1OrV2) => false,
(1, Version::V1OrV2) |
(1, Version::V2Only) => true,
_ => { return Err(error::Unspecified); }
};
let actual_alg_id =
try!(der::expect_tag_and_get_value(input, der::Tag::Sequence));
if actual_alg_id != alg_id {
return Err(error::Unspecified);
}
let private_key =
try!(der::expect_tag_and_get_value(input, der::Tag::OctetString));
if input.peek(der::Tag::ContextSpecificConstructed0 as u8) {
let _ = try!(der::expect_tag_and_get_value(input,
der::Tag::ContextSpecificConstructed0));
}
let public_key = if require_public_key {
Some(try!(der::nested(
input, der::Tag::ContextSpecificConstructed1,
error::Unspecified, der::bit_string_with_no_unused_bits)))
} else {
None
};
Ok((private_key, public_key))
})
})
}