/// All the nonces are the same length. Exploit that. pubconst NONCE_LEN: usize = 12; /// The portion of the nonce that is a counter. const COUNTER_LEN: usize = mem::size_of::<SequenceNumber>(); /// The NSS API insists on us identifying the tag separately, which is awful. /// All of the AEAD functions here have a tag of this length, so use a fixed offset. const TAG_LEN: usize = 16;
pubtype SequenceNumber = u64;
/// All the lengths used by `PK11_AEADOp` are signed. This converts to that. fn c_int_len<T>(l: T) -> c_int where
T: TryInto<c_int>,
T::Error: std::error::Error,
{
l.try_into().unwrap()
}
pubfn seal(&mutself, aad: &[u8], pt: &[u8]) -> Res<Vec<u8>> {
assert_eq!(self.mode, Mode::Encrypt); // A copy for the nonce generator to write into. But we don't use the value. letmut nonce = self.nonce_base; // Ciphertext with enough space for the tag. // Even though we give the operation a separate buffer for the tag, // reserve the capacity on allocation. letmut ct = vec![0; pt.len() + TAG_LEN]; letmut ct_len: c_int = 0; letmut tag = vec![0; TAG_LEN];
secstatus_to_res(unsafe {
PK11_AEADOp(
*self.ctx,
CK_GENERATOR_FUNCTION::from(CKG_GENERATE_COUNTER_XOR),
c_int_len(NONCE_LEN - COUNTER_LEN), // Fixed portion of the nonce.
nonce.as_mut_ptr(),
c_int_len(nonce.len()),
aad.as_ptr(),
c_int_len(aad.len()),
ct.as_mut_ptr(),
&mut ct_len,
c_int_len(ct.len()), // signed :(
tag.as_mut_ptr(),
c_int_len(tag.len()),
pt.as_ptr(),
c_int_len(pt.len()),
)
})?;
ct.truncate(usize::try_from(ct_len).unwrap());
debug_assert_eq!(ct.len(), pt.len());
ct.append(&mut tag);
Ok(ct)
}
pubfn open(&mutself, aad: &[u8], seq: SequenceNumber, ct: &[u8]) -> Res<Vec<u8>> {
assert_eq!(self.mode, Mode::Decrypt); letmut nonce = self.nonce_base; for (i, n) in nonce.iter_mut().rev().take(COUNTER_LEN).enumerate() {
*n ^= u8::try_from((seq >> (8 * i)) & 0xff).unwrap();
} letmut pt = vec![0; ct.len()]; // NSS needs more space than it uses for plaintext. letmut pt_len: c_int = 0; let pt_expected = ct.len().checked_sub(TAG_LEN).ok_or(Error::Truncated)?;
secstatus_to_res(unsafe {
PK11_AEADOp(
*self.ctx,
CK_GENERATOR_FUNCTION::from(CKG_NO_GENERATE),
c_int_len(NONCE_LEN - COUNTER_LEN), // Fixed portion of the nonce.
nonce.as_mut_ptr(),
c_int_len(nonce.len()),
aad.as_ptr(),
c_int_len(aad.len()),
pt.as_mut_ptr(),
&mut pt_len,
c_int_len(pt.len()), // signed :(
ct.as_ptr().add(pt_expected) as *mut _, // const cast :(
c_int_len(TAG_LEN),
ct.as_ptr(),
c_int_len(pt_expected),
)
})?; let len = usize::try_from(pt_len).unwrap();
debug_assert_eq!(len, pt_expected);
pt.truncate(len);
Ok(pt)
}
}
#[cfg(test)] mod test { usesuper::{ super::{super::hpke::Aead as AeadId, init},
Aead, Mode, SequenceNumber, NONCE_LEN,
};
/// Check that the first invocation of encryption matches expected values. /// Also check decryption of the same. fn check0(
algorithm: AeadId,
key: &[u8],
nonce: &[u8; NONCE_LEN],
aad: &[u8],
pt: &[u8],
ct: &[u8],
) {
init(); let k = Aead::import_key(algorithm, key).unwrap();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.