use nom::combinator::map;
use nom::multi::length_data;
use nom::number::streaming::be_u16;
use nom::sequence::pair;
use nom::IResult;
use nom_derive::*;
use rusticata_macros::newtype_enum;
#[derive(Clone, Debug, PartialEq, Eq, Nom)]
pub struct HashAlgorithm(pub u8);
newtype_enum! {
impl display HashAlgorithm {
None = 0,
Md5 = 1,
Sha1 = 2,
Sha224 = 3,
Sha256 = 4,
Sha384 = 5,
Sha512 = 6,
Intrinsic = 8, }
}
#[derive(Clone, Debug, PartialEq, Eq, Nom)]
pub struct SignAlgorithm(pub u8);
newtype_enum! {
impl display SignAlgorithm {
Anonymous = 0,
Rsa = 1,
Dsa = 2,
Ecdsa = 3,
Ed25519 = 7, Ed448 = 8, }
}
#[derive(Clone, PartialEq, Nom)]
pub struct SignatureAndHashAlgorithm {
pub hash: HashAlgorithm,
pub sign: SignAlgorithm,
}
#[derive(Debug, PartialEq, Eq, Nom)]
pub struct SignatureScheme(pub u16);
newtype_enum! {
impl display SignatureScheme {
rsa_pkcs1_sha256 = 0x0401,
rsa_pkcs1_sha384 = 0x0501,
rsa_pkcs1_sha512 = 0x0601,
ecdsa_secp256r1_sha256 = 0x0403,
ecdsa_secp384r1_sha384 = 0x0503,
ecdsa_secp521r1_sha512 = 0x0603,
sm2sig_sm3 = 0x0708,
rsa_pss_rsae_sha256 = 0x0804,
rsa_pss_rsae_sha384 = 0x0805,
rsa_pss_rsae_sha512 = 0x0806,
ed25519 = 0x0807,
ed448 = 0x0808,
rsa_pss_pss_sha256 = 0x0809,
rsa_pss_pss_sha384 = 0x080a,
rsa_pss_pss_sha512 = 0x080b,
ecdsa_brainpoolP256r1tls13_sha256 = 0x081a,
ecdsa_brainpoolP384r1tls13_sha384 = 0x081b,
ecdsa_brainpoolP512r1tls13_sha512 = 0x081c,
rsa_pkcs1_sha1 = 0x0201,
ecdsa_sha1 = 0x0203,
}
}
impl SignatureScheme {
pub fn is_reserved(&self) -> bool {
self.0 >= 0xfe00 && self.0 < 0xff00
}
pub fn hash_alg(&self) -> u8 {
((self.0 >> 8) & 0xff) as u8
}
pub fn sign_alg(&self) -> u8 {
(self.0 & 0xff) as u8
}
}
#[derive(Clone, PartialEq)]
pub struct DigitallySigned<'a> {
pub alg: Option<SignatureAndHashAlgorithm>,
pub data: &'a [u8],
}
pub fn parse_digitally_signed_old(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
map(length_data(be_u16), |data| DigitallySigned {
alg: None,
data,
})(i)
}
pub fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
let (i, hash) = HashAlgorithm::parse(i)?;
let (i, sign) = SignAlgorithm::parse(i)?;
let (i, data) = length_data(be_u16)(i)?;
let signed = DigitallySigned {
alg: Some(SignatureAndHashAlgorithm { hash, sign }),
data,
};
Ok((i, signed))
}
pub fn parse_content_and_signature<'a, F, T>(
i: &'a [u8],
fun: F,
ext: bool,
) -> IResult<&'a [u8], (T, DigitallySigned<'a>)>
where
F: Fn(&'a [u8]) -> IResult<&'a [u8], T>,
{
if ext {
pair(fun, parse_digitally_signed)(i)
} else {
pair(fun, parse_digitally_signed_old)(i)
}
}