usecrate::p11::Context; usecrate::p11::{ self, PK11_AEADOp, PK11_CreateContextBySymKey, CKA_DECRYPT, CKA_ENCRYPT, CKA_NSS_MESSAGE,
CKG_GENERATE_COUNTER_XOR, CKG_NO_GENERATE, CKM_AES_GCM, CKM_CHACHA20_POLY1305,
CK_ATTRIBUTE_TYPE, CK_GENERATOR_FUNCTION, CK_MECHANISM_TYPE,
}; usecrate::secstatus_to_res; usecrate::SECItemBorrowed; usecrate::{Error, SymKey}; use std::convert::TryFrom; use std::convert::TryInto; use std::mem; use std::os::raw::c_int;
/// 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()
}
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)
}
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::AeadTruncated)?;
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()),
ct.as_ptr().add(pt_expected) as *mut _,
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::init, Aead, AeadAlgorithms, Mode, SequenceNumber, NONCE_LEN};
/// Check that the first invocation of encryption matches expected values. /// Also check decryption of the same. fn check0(
algorithm: AeadAlgorithms,
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.