certificate: parse sig-alg
This commit is contained in:
parent
eadf776da3
commit
1c689b3535
|
@ -1,6 +1,8 @@
|
|||
use num_enum::IntoPrimitive;
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub struct Certificate<'a> {
|
||||
tbs_certificate: TBSCertificate<'a>,
|
||||
signature_algorithm: AlgorithmIdentifier<'a>,
|
||||
|
@ -17,7 +19,7 @@ pub struct TBSCertificate<'a> {
|
|||
subject_public_key_info: SubjectPublicKeyInfo<'a>,
|
||||
issuer_unique_id: Option<&'a [u8]>,
|
||||
subject_unique_id: Option<&'a [u8]>,
|
||||
extensions: Extensions,
|
||||
extensions: Extensions<'a>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
|
@ -30,8 +32,8 @@ pub enum Version {
|
|||
}
|
||||
|
||||
pub struct Validity<'a> {
|
||||
not_before: Time<'a>,
|
||||
not_after: Time<'a>,
|
||||
pub not_before: Time<'a>,
|
||||
pub not_after: Time<'a>,
|
||||
}
|
||||
|
||||
pub enum Time<'a> {
|
||||
|
@ -40,12 +42,31 @@ pub enum Time<'a> {
|
|||
}
|
||||
|
||||
pub struct SubjectPublicKeyInfo<'a> {
|
||||
algorithm: AlgorithmIdentifier<'a>,
|
||||
subject_public_key: &'a [u8],
|
||||
pub algorithm: AlgorithmIdentifier<'a>,
|
||||
pub subject_public_key: &'a [u8],
|
||||
}
|
||||
|
||||
pub struct Extensions {
|
||||
|
||||
pub struct Extensions<'a> {
|
||||
extensions: Vec<Extension<'a>>
|
||||
}
|
||||
|
||||
pub enum Extension<'a> {
|
||||
KeyUsage {
|
||||
// Acceptable usage of this certificate
|
||||
// Cross verify with ExtendedKeyUsage
|
||||
usage: u8
|
||||
},
|
||||
CertificatePolicies {
|
||||
// Policies listed in an extension
|
||||
// Need to verify its validity
|
||||
policies: Vec<&'a [u8]>
|
||||
},
|
||||
SubjectAlternativeName,
|
||||
BasicConstraints {
|
||||
is_ca: bool,
|
||||
path_len_constraint: Option<u8>,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
pub struct AlgorithmIdentifier<'a> {
|
||||
|
|
101
src/parse.rs
101
src/parse.rs
|
@ -16,6 +16,10 @@ use crate::tls_packet::*;
|
|||
use crate::certificate::Certificate as Asn1DerCertificate;
|
||||
use crate::certificate::Version as Asn1DerVersion;
|
||||
use crate::certificate::AlgorithmIdentifier as Asn1DerAlgId;
|
||||
use crate::certificate::Time as Asn1DerTime;
|
||||
use crate::certificate::Validity as Asn1DerValidity;
|
||||
use crate::certificate::SubjectPublicKeyInfo as Asn1DerSubjectPublicKeyInfo;
|
||||
use crate::certificate::Extensions as Asn1DerExtensions;
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use core::convert::TryInto;
|
||||
|
@ -362,6 +366,8 @@ pub fn parse_asn1_der_header(bytes: &[u8]) -> IResult<&[u8], (u8, usize)> {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Not return length
|
||||
// It is quite useless when the value slice of the exact same length is returned
|
||||
pub fn parse_asn1_der_object(bytes: &[u8]) -> IResult<&[u8], (u8, usize, &[u8])> {
|
||||
let (rest, (tag, length)) = parse_asn1_der_header(bytes)?;
|
||||
let (rest, value) = take(length)(rest)?;
|
||||
|
@ -404,6 +410,26 @@ pub fn parse_asn1_der_integer(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|||
if tag_val != 0x02 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
// Consume the leading 0x00 byte
|
||||
let (value, _) = tag(&[0x00])(value)?;
|
||||
Ok((rest, value))
|
||||
}
|
||||
|
||||
// BIT STRING: tag: 0x03
|
||||
// Assumption: No unused bits at the last byte
|
||||
// Public keys are always represented in bytes
|
||||
pub fn parse_asn1_der_bit_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag is indeed 0x03
|
||||
if tag_val != 0x03 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
// Dump `unused_bit` field
|
||||
let (value, unused_bit_byte) = take(1_usize)(value)?;
|
||||
// Assert no unused bits, otherwise it is a malformatted key
|
||||
if value[0] != 0 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
Ok((rest, value))
|
||||
}
|
||||
|
||||
|
@ -446,8 +472,77 @@ pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
|||
Ok((rest, value))
|
||||
}
|
||||
|
||||
// Parser for Time Validity Structure
|
||||
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
// Parser for Time Validity Sequence Structure (0x30)
|
||||
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], Asn1DerValidity> {
|
||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
||||
|
||||
// Verify the tag_val is indeed 0x30
|
||||
if tag_val != 0x30 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
let (_, (not_before, not_after)) = complete(
|
||||
tuple((
|
||||
parse_ans1_der_time,
|
||||
parse_ans1_der_time
|
||||
))
|
||||
)(value)?;
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerValidity {
|
||||
not_before,
|
||||
not_after,
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Parser for Time Representation (0x17: UTCTime, 0x18: GeneralizedTime)
|
||||
pub fn parse_ans1_der_time(bytes: &[u8]) -> IResult<&[u8], Asn1DerTime> {
|
||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
||||
// Handle UTCTime, Gen.Time and Invalid Tag values
|
||||
match tag_val {
|
||||
0x17 => {
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerTime::UTCTime(value)
|
||||
))
|
||||
},
|
||||
0x18 => {
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerTime::GeneralizedTime(value)
|
||||
))
|
||||
},
|
||||
_ => Err(nom::Err::Failure((&[], ErrorKind::Verify)))
|
||||
}
|
||||
}
|
||||
|
||||
// Parser for SubjectKeyPublicInfo (Sequence: 0x30)
|
||||
pub fn parse_asn1_der_subject_key_public_info(bytes: &[u8]) -> IResult<&[u8], Asn1DerSubjectPublicKeyInfo> {
|
||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag_val is indeed 0x30
|
||||
if tag_val != 0x30 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
let (_, (algorithm, subject_public_key)) = complete(
|
||||
tuple((
|
||||
parse_asn1_der_algorithm_identifier,
|
||||
parse_asn1_der_bit_string,
|
||||
))
|
||||
)(value)?;
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerSubjectPublicKeyInfo {
|
||||
algorithm,
|
||||
subject_public_key
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// Parser for extensions (Sequence: 0xA3)
|
||||
pub fn parse_asn1_der_extensions(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensions> {
|
||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag_val is indeed 0xA3
|
||||
if tag_val != 0xA3 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue