address feedback

This commit is contained in:
Jan Winkelmann (keks)
2025-02-27 11:30:51 +01:00
parent b84e0beae8
commit 01a1408044
5 changed files with 61 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
pub mod keyed_hash_incorrect_hmac_blake2b {
use crate::primitives::keyed_hash::*;
// These constants describe how they are used here, not what the algorithm defines.
pub const KEY_LEN: usize = 32;
pub const OUT_LEN: usize = 32;
@@ -10,6 +11,7 @@ pub mod keyed_hash_incorrect_hmac_blake2b {
pub mod keyed_hash_blake2b {
use crate::primitives::keyed_hash::*;
// These constants describe how they are used here, not what the algorithm defines.
pub const KEY_LEN: usize = 32;
pub const OUT_LEN: usize = 32;
@@ -19,6 +21,7 @@ pub mod keyed_hash_blake2b {
pub mod keyed_hash_shake256 {
use crate::primitives::keyed_hash::*;
// These constants describe how they are used here, not what the algorithm defines.
pub const KEY_LEN: usize = 32;
pub const OUT_LEN: usize = 32;
@@ -28,6 +31,7 @@ pub mod keyed_hash_shake256 {
pub mod aead_chacha20poly1305 {
use crate::primitives::aead::*;
// See https://datatracker.ietf.org/doc/html/rfc7539#section-2.8
pub const KEY_LEN: usize = 32;
pub const NONCE_LEN: usize = 12;
pub const TAG_LEN: usize = 16;
@@ -38,6 +42,7 @@ pub mod aead_chacha20poly1305 {
pub mod aead_xchacha20poly1305 {
use crate::primitives::aead::*;
// See https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03
pub const KEY_LEN: usize = 32;
pub const NONCE_LEN: usize = 24;
pub const TAG_LEN: usize = 16;
@@ -48,7 +53,7 @@ pub mod aead_xchacha20poly1305 {
pub mod kem_kyber512 {
use crate::primitives::kem::*;
// page 33 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf
// page 39 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
// (which is ml-kem instead of kyber, but it's the same)
pub const SK_LEN: usize = 1632;
pub const PK_LEN: usize = 800;

View File

@@ -1,3 +1,4 @@
use rosenpass_to::{ops::copy_slice, To as _};
use thiserror::Error;
pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize> {
@@ -33,6 +34,28 @@ pub trait AeadWithNonceInCiphertext<
const TAG_LEN: usize,
>: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>
{
fn encrypt_with_nonce_in_ctxt(
&self,
ciphertext: &mut [u8],
key: &[u8; KEY_LEN],
nonce: &[u8; NONCE_LEN],
ad: &[u8],
plaintext: &[u8],
) -> Result<(), Error> {
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < NONCE_LEN + TAG_LEN
|| ciphertext.len() - TAG_LEN - NONCE_LEN < plaintext.len()
{
return Err(Error::InvalidLengths);
}
let (n, rest) = ciphertext.split_at_mut(NONCE_LEN);
copy_slice(nonce).to(n);
self.encrypt(rest, key, nonce, ad, plaintext)
}
fn decrypt_with_nonce_in_ctxt(
&self,
plaintext: &mut [u8],
@@ -40,7 +63,11 @@ pub trait AeadWithNonceInCiphertext<
ad: &[u8],
ciphertext: &[u8],
) -> Result<(), Error> {
if ciphertext.len() < plaintext.len() + TAG_LEN + NONCE_LEN {
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < NONCE_LEN + TAG_LEN
|| ciphertext.len() - TAG_LEN - NONCE_LEN < plaintext.len()
{
return Err(Error::InvalidLengths);
}

View File

@@ -25,7 +25,9 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
ad: &[u8],
plaintext: &[u8],
) -> Result<(), AeadError> {
if ciphertext.len() < plaintext.len() + TAG_LEN {
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
return Err(AeadError::InvalidLengths);
}
@@ -53,7 +55,9 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
ad: &[u8],
ciphertext: &[u8],
) -> Result<(), AeadError> {
if ciphertext.len() < plaintext.len() + TAG_LEN {
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
return Err(AeadError::InvalidLengths);
}

View File

@@ -25,12 +25,17 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
ad: &[u8],
plaintext: &[u8],
) -> Result<(), AeadError> {
let nonce = GenericArray::from_slice(nonce);
let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN);
let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN);
copy_slice(nonce).to(n);
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
return Err(AeadError::InvalidLengths);
}
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
copy_slice(plaintext).to(ct);
let nonce = GenericArray::from_slice(nonce);
// This only fails if the length is wrong, which really shouldn't happen and would
// constitute an internal error.
let encrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?;
@@ -50,6 +55,12 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
ad: &[u8],
ciphertext: &[u8],
) -> Result<(), AeadError> {
// The comparison looks complicated, but we need to do it this way to prevent
// over/underflows.
if ciphertext.len() < TAG_LEN || ciphertext.len() - TAG_LEN < plaintext.len() {
return Err(AeadError::InvalidLengths);
}
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
let nonce = GenericArray::from_slice(nonce);
let tag = GenericArray::from_slice(mac);

View File

@@ -2241,7 +2241,7 @@ impl CryptoServer {
msg_out.inner.msg_type = MsgType::CookieReply.into();
msg_out.inner.sid = rx_sid;
XAead.encrypt(
XAead.encrypt_with_nonce_in_ctxt(
&mut msg_out.inner.cookie_encrypted[..],
&cookie_key,
&nonce.value,
@@ -3348,6 +3348,7 @@ impl HandshakeState {
self.mix(pk)?.mix(shk.secret())?.mix(ct)
}
/// Calls [`Self::encaps_and_mix`] with the generic parameters that match [`StaticKem`].
pub fn encaps_and_mix_static(
&mut self,
ct: &mut [u8; StaticKem::CT_LEN],
@@ -3356,6 +3357,7 @@ impl HandshakeState {
self.encaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(ct, pk)
}
/// Calls [`Self::encaps_and_mix`] with the generic parameters that match [`EphemeralKem`].
pub fn encaps_and_mix_ephemeral(
&mut self,
ct: &mut [u8; EphemeralKem::CT_LEN],
@@ -3385,6 +3387,7 @@ impl HandshakeState {
self.mix(pk)?.mix(shk.secret())?.mix(ct)
}
/// Calls [`Self::decaps_and_mix`] with the generic parameters that match [`StaticKem`].
pub fn decaps_and_mix_static(
&mut self,
sk: &[u8; StaticKem::SK_LEN],
@@ -3394,6 +3397,7 @@ impl HandshakeState {
self.decaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(sk, pk, ct)
}
/// Calls [`Self::decaps_and_mix`] with the generic parameters that match [`EphemeralKem`].
pub fn decaps_and_mix_ephemeral(
&mut self,
sk: &[u8; EphemeralKem::SK_LEN],
@@ -3448,7 +3452,7 @@ impl HandshakeState {
let k = bk.get(srv).value.secret();
let pt = biscuit.as_bytes();
XAead.encrypt(biscuit_ct, k, &*n, &ad, pt)?;
XAead.encrypt_with_nonce_in_ctxt(biscuit_ct, k, &*n, &ad, pt)?;
self.mix(biscuit_ct)
}