mod certificate;
mod certificate_request;
mod certificate_verify;
mod client_hello;
mod client_key_exchange;
mod digitally_signed;
mod extension;
mod extensions;
mod finished;
mod handshake;
mod hello_verify;
mod id;
mod named_group;
mod record;
mod server_hello;
mod server_key_exchange;
mod wrapped;
use arrayvec::ArrayVec;
pub use certificate::Certificate;
pub use certificate_request::CertificateRequest;
pub use certificate_verify::CertificateVerify;
pub use client_hello::ClientHello;
pub use client_key_exchange::{ClientKeyExchange, ClientPskKeys, ExchangeKeys};
pub use digitally_signed::DigitallySigned;
pub use extension::{Extension, ExtensionType};
pub use extensions::ec_point_formats::ECPointFormatsExtension;
pub use extensions::signature_algorithms::SignatureAlgorithmsExtension;
pub use extensions::supported_groups::SupportedGroupsExtension;
pub use extensions::use_srtp::{SrtpProfileId, SrtpProfileVec, UseSrtpExtension};
pub use finished::Finished;
pub use handshake::{Body, Handshake, Header, MessageType};
pub use hello_verify::HelloVerifyRequest;
pub use id::{Cookie, SessionId};
pub use named_group::CurveType;
pub use record::DTLSRecord;
pub use crate::types::{
CompressionMethod, ContentType, HashAlgorithm, NamedGroup, NamedGroupVec, ProtocolVersion,
Random, Sequence, SignatureAlgorithm,
};
pub use server_hello::ServerHello;
pub use server_key_exchange::{PskParams, ServerKeyExchange, ServerKeyExchangeParams};
pub use wrapped::{Asn1Cert, DistinguishedName};
use nom::IResult;
use nom::number::complete::{be_u8, be_u16};
pub type CipherSuiteVec = ArrayVec<Dtls12CipherSuite, { Dtls12CipherSuite::supported().len() }>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Dtls12CipherSuite {
ECDHE_ECDSA_AES256_GCM_SHA384, ECDHE_ECDSA_AES128_GCM_SHA256, ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
PSK_AES128_CCM_8,
Unknown(u16),
}
impl Default for Dtls12CipherSuite {
fn default() -> Self {
Self::Unknown(0)
}
}
impl Dtls12CipherSuite {
pub fn from_u16(value: u16) -> Self {
match value {
0xC02C => Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384,
0xC02B => Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256,
0xCCA9 => Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
0xC0A8 => Dtls12CipherSuite::PSK_AES128_CCM_8,
_ => Dtls12CipherSuite::Unknown(value),
}
}
pub fn as_u16(&self) -> u16 {
match self {
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384 => 0xC02C,
Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256 => 0xC02B,
Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256 => 0xCCA9,
Dtls12CipherSuite::PSK_AES128_CCM_8 => 0xC0A8,
Dtls12CipherSuite::Unknown(value) => *value,
}
}
pub fn parse(input: &[u8]) -> IResult<&[u8], Dtls12CipherSuite> {
let (input, value) = be_u16(input)?;
Ok((input, Dtls12CipherSuite::from_u16(value)))
}
pub fn verify_data_length(&self) -> usize {
match self {
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384
| Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256
| Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256
| Dtls12CipherSuite::PSK_AES128_CCM_8 => 12,
Dtls12CipherSuite::Unknown(_) => 12, }
}
pub fn as_key_exchange_algorithm(&self) -> KeyExchangeAlgorithm {
match self {
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384
| Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256
| Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256 => {
KeyExchangeAlgorithm::EECDH
}
Dtls12CipherSuite::PSK_AES128_CCM_8 => KeyExchangeAlgorithm::PSK,
Dtls12CipherSuite::Unknown(_) => KeyExchangeAlgorithm::Unknown,
}
}
pub fn has_ecc(&self) -> bool {
matches!(
self,
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384
| Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256
| Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256
)
}
pub fn is_psk(&self) -> bool {
matches!(self, Dtls12CipherSuite::PSK_AES128_CCM_8)
}
pub const fn all() -> &'static [Dtls12CipherSuite; 4] {
&[
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384,
Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256,
Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
Dtls12CipherSuite::PSK_AES128_CCM_8,
]
}
pub fn compatible_with_certificate(
cert_type: SignatureAlgorithm,
) -> &'static [Dtls12CipherSuite; 3] {
match cert_type {
SignatureAlgorithm::ECDSA => &[
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384,
Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256,
Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
],
_ => panic!("Need either RSA or ECDSA certificate"),
}
}
fn need_encrypt_then_mac(&self) -> bool {
false
}
pub fn hash_algorithm(&self) -> HashAlgorithm {
match self {
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384 => HashAlgorithm::SHA384,
Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256
| Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256
| Dtls12CipherSuite::PSK_AES128_CCM_8 => HashAlgorithm::SHA256,
Dtls12CipherSuite::Unknown(_) => HashAlgorithm::Unknown(0),
}
}
pub fn signature_algorithm(&self) -> Option<SignatureAlgorithm> {
match self {
Dtls12CipherSuite::ECDHE_ECDSA_AES256_GCM_SHA384
| Dtls12CipherSuite::ECDHE_ECDSA_AES128_GCM_SHA256
| Dtls12CipherSuite::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256 => {
Some(SignatureAlgorithm::ECDSA)
}
Dtls12CipherSuite::PSK_AES128_CCM_8 => None,
Dtls12CipherSuite::Unknown(_) => Some(SignatureAlgorithm::Unknown(0)),
}
}
pub fn is_supported(&self) -> bool {
Self::supported().contains(self)
}
pub const fn supported() -> &'static [Dtls12CipherSuite; 4] {
Self::all()
}
}
pub type CompressionMethodVec =
ArrayVec<CompressionMethod, { CompressionMethod::supported().len() }>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)]
pub enum KeyExchangeAlgorithm {
EECDH,
PSK,
Unknown,
}
pub type CertificateTypeVec =
ArrayVec<ClientCertificateType, { ClientCertificateType::supported().len() }>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum ClientCertificateType {
RSA_SIGN,
DSS_SIGN,
RSA_FIXED_DH,
DSS_FIXED_DH,
RSA_EPHEMERAL_DH,
DSS_EPHEMERAL_DH,
FORTEZZA_DMS,
ECDSA_SIGN,
Unknown(u8),
}
impl Default for ClientCertificateType {
fn default() -> Self {
Self::Unknown(0)
}
}
impl ClientCertificateType {
pub fn from_u8(value: u8) -> Self {
match value {
1 => ClientCertificateType::RSA_SIGN,
2 => ClientCertificateType::DSS_SIGN,
3 => ClientCertificateType::RSA_FIXED_DH,
4 => ClientCertificateType::DSS_FIXED_DH,
5 => ClientCertificateType::RSA_EPHEMERAL_DH,
6 => ClientCertificateType::DSS_EPHEMERAL_DH,
20 => ClientCertificateType::FORTEZZA_DMS,
64 => ClientCertificateType::ECDSA_SIGN,
_ => ClientCertificateType::Unknown(value),
}
}
pub fn is_supported(&self) -> bool {
Self::supported().contains(self)
}
pub const fn supported() -> &'static [ClientCertificateType; 1] {
&[ClientCertificateType::ECDSA_SIGN]
}
pub fn as_u8(&self) -> u8 {
match self {
ClientCertificateType::RSA_SIGN => 1,
ClientCertificateType::DSS_SIGN => 2,
ClientCertificateType::RSA_FIXED_DH => 3,
ClientCertificateType::DSS_FIXED_DH => 4,
ClientCertificateType::RSA_EPHEMERAL_DH => 5,
ClientCertificateType::DSS_EPHEMERAL_DH => 6,
ClientCertificateType::FORTEZZA_DMS => 20,
ClientCertificateType::ECDSA_SIGN => 64,
ClientCertificateType::Unknown(value) => *value,
}
}
pub fn parse(input: &[u8]) -> IResult<&[u8], ClientCertificateType> {
let (input, value) = be_u8(input)?;
Ok((input, ClientCertificateType::from_u8(value)))
}
}
pub type SignatureAndHashAlgorithmVec =
ArrayVec<SignatureAndHashAlgorithm, { SignatureAndHashAlgorithm::supported().len() }>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct SignatureAndHashAlgorithm {
pub hash: HashAlgorithm,
pub signature: SignatureAlgorithm,
}
impl SignatureAndHashAlgorithm {
pub const fn new(hash: HashAlgorithm, signature: SignatureAlgorithm) -> Self {
SignatureAndHashAlgorithm { hash, signature }
}
pub fn from_u16(value: u16) -> Self {
let hash = HashAlgorithm::from_u8((value >> 8) as u8);
let signature = SignatureAlgorithm::from_u8(value as u8);
SignatureAndHashAlgorithm { hash, signature }
}
pub fn as_u16(&self) -> u16 {
((self.hash.as_u8() as u16) << 8) | (self.signature.as_u8() as u16)
}
pub fn parse(input: &[u8]) -> IResult<&[u8], SignatureAndHashAlgorithm> {
let (input, value) = be_u16(input)?;
Ok((input, SignatureAndHashAlgorithm::from_u16(value)))
}
#[allow(dead_code)]
pub const fn all() -> &'static [SignatureAndHashAlgorithm; 4] {
Self::supported()
}
pub const fn supported() -> &'static [SignatureAndHashAlgorithm; 4] {
const SUPPORTED: &[SignatureAndHashAlgorithm; 4] = &[
SignatureAndHashAlgorithm::new(HashAlgorithm::SHA256, SignatureAlgorithm::ECDSA),
SignatureAndHashAlgorithm::new(HashAlgorithm::SHA384, SignatureAlgorithm::ECDSA),
SignatureAndHashAlgorithm::new(HashAlgorithm::SHA256, SignatureAlgorithm::RSA),
SignatureAndHashAlgorithm::new(HashAlgorithm::SHA384, SignatureAlgorithm::RSA),
];
SUPPORTED
}
pub fn is_supported(&self) -> bool {
Self::supported().contains(self)
}
}