boring2/quinn-boring/src/suite.rs

106 lines
3.7 KiB
Rust

use crate::aead::Aead;
use crate::error::{Error, Result};
use crate::hkdf::Hkdf;
use boring_sys as bffi;
use std::fmt::{Debug, Formatter};
use std::sync::LazyLock;
// For AEAD_AES_128_GCM and AEAD_AES_256_GCM ... endpoints that do not send
// packets larger than 2^11 bytes cannot protect more than 2^28 packets.
// https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-confidentiality-limit
const AES_CONFIDENTIALITY_LIMIT: u64 = 2u64.pow(28);
// For AEAD_CHACHA20_POLY1305, the confidentiality limit is greater than the
// number of possible packets (2^62) and so can be disregarded.
// https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-limits-on-aead-usage
const CHACHA20_POLY1305_CONFIDENTIALITY_LIMIT: u64 = u64::MAX;
// For AEAD_AES_128_GCM ... endpoints that do not attempt to remove
// protection from packets larger than 2^11 bytes can attempt to remove
// protection from at most 2^57 packets.
// For AEAD_AES_256_GCM [the limit] is substantially larger than the limit for
// AEAD_AES_128_GCM. However, this document recommends that the same limit be
// applied to both functions as either limit is acceptably large.
// https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-integrity-limit
const AES_INTEGRITY_LIMIT: u64 = 2u64.pow(57);
// For AEAD_CHACHA20_POLY1305, the integrity limit is 2^36 invalid packets.
// https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-limits-on-aead-usage
const CHACHA20_POLY1305_INTEGRITY_LIMIT: u64 = 2u64.pow(36);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ID {
Aes128GcmSha256,
Aes256GcmSha384,
Chacha20Poly1305Sha256,
}
#[derive(Eq, PartialEq)]
pub(crate) struct CipherSuite {
pub(crate) id: ID,
pub(crate) hkdf: Hkdf,
pub(crate) aead: &'static Aead,
pub(crate) confidentiality_limit: u64,
pub(crate) integrity_limit: u64,
}
impl Debug for CipherSuite {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.id, f)
}
}
static AES128_GCM_SHA256: LazyLock<CipherSuite> = LazyLock::new(|| CipherSuite {
id: ID::Aes128GcmSha256,
hkdf: Hkdf::sha256(),
aead: Aead::aes128_gcm(),
confidentiality_limit: AES_CONFIDENTIALITY_LIMIT,
integrity_limit: AES_INTEGRITY_LIMIT,
});
static AES256_GCM_SHA384: LazyLock<CipherSuite> = LazyLock::new(|| CipherSuite {
id: ID::Aes256GcmSha384,
hkdf: Hkdf::sha384(),
aead: Aead::aes256_gcm(),
confidentiality_limit: AES_CONFIDENTIALITY_LIMIT,
integrity_limit: AES_INTEGRITY_LIMIT,
});
static CHACHA20_POLY1305_SHA256: LazyLock<CipherSuite> = LazyLock::new(|| CipherSuite {
id: ID::Chacha20Poly1305Sha256,
hkdf: Hkdf::sha256(),
aead: Aead::chacha20_poly1305(),
confidentiality_limit: CHACHA20_POLY1305_CONFIDENTIALITY_LIMIT,
integrity_limit: CHACHA20_POLY1305_INTEGRITY_LIMIT,
});
unsafe impl Send for CipherSuite {}
unsafe impl Sync for CipherSuite {}
impl CipherSuite {
#[inline]
pub(crate) fn aes128_gcm_sha256() -> &'static Self {
&AES128_GCM_SHA256
}
#[inline]
pub(crate) fn aes256_gcm_sha384() -> &'static Self {
&AES256_GCM_SHA384
}
#[inline]
pub(crate) fn chacha20_poly1305_sha256() -> &'static Self {
&CHACHA20_POLY1305_SHA256
}
#[inline]
pub(crate) fn from_cipher(cipher: *const bffi::SSL_CIPHER) -> Result<&'static Self> {
match unsafe { bffi::SSL_CIPHER_get_id(cipher) } as i32 {
bffi::TLS1_CK_AES_128_GCM_SHA256 => Ok(Self::aes128_gcm_sha256()),
bffi::TLS1_CK_AES_256_GCM_SHA384 => Ok(Self::aes256_gcm_sha384()),
bffi::TLS1_CK_CHACHA20_POLY1305_SHA256 => Ok(Self::chacha20_poly1305_sha256()),
id => Err(Error::invalid_input(format!("invalid cipher id: {id}"))),
}
}
}