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))
})
})
}
pub fn wrap_key(template: &[u8], private_key_index: usize, private_key: &[u8],
public_key: &[u8], bytes: &mut [u8]) {
let (before_private_key, after_private_key) =
template.split_at(private_key_index);
let private_key_end_index = private_key_index + private_key.len();
bytes[..private_key_index].copy_from_slice(before_private_key);
bytes[private_key_index..private_key_end_index]
.copy_from_slice(&private_key);
bytes[private_key_end_index..
(private_key_end_index + after_private_key.len())]
.copy_from_slice(after_private_key);
bytes[(private_key_end_index + after_private_key.len())..]
.copy_from_slice(public_key);
}