certificate: parse sig-alg
This commit is contained in:
parent
eadf776da3
commit
1c689b3535
|
@ -1,6 +1,8 @@
|
||||||
use num_enum::IntoPrimitive;
|
use num_enum::IntoPrimitive;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
pub struct Certificate<'a> {
|
pub struct Certificate<'a> {
|
||||||
tbs_certificate: TBSCertificate<'a>,
|
tbs_certificate: TBSCertificate<'a>,
|
||||||
signature_algorithm: AlgorithmIdentifier<'a>,
|
signature_algorithm: AlgorithmIdentifier<'a>,
|
||||||
|
@ -17,7 +19,7 @@ pub struct TBSCertificate<'a> {
|
||||||
subject_public_key_info: SubjectPublicKeyInfo<'a>,
|
subject_public_key_info: SubjectPublicKeyInfo<'a>,
|
||||||
issuer_unique_id: Option<&'a [u8]>,
|
issuer_unique_id: Option<&'a [u8]>,
|
||||||
subject_unique_id: Option<&'a [u8]>,
|
subject_unique_id: Option<&'a [u8]>,
|
||||||
extensions: Extensions,
|
extensions: Extensions<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||||
|
@ -30,8 +32,8 @@ pub enum Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Validity<'a> {
|
pub struct Validity<'a> {
|
||||||
not_before: Time<'a>,
|
pub not_before: Time<'a>,
|
||||||
not_after: Time<'a>,
|
pub not_after: Time<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Time<'a> {
|
pub enum Time<'a> {
|
||||||
|
@ -40,11 +42,30 @@ pub enum Time<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SubjectPublicKeyInfo<'a> {
|
pub struct SubjectPublicKeyInfo<'a> {
|
||||||
algorithm: AlgorithmIdentifier<'a>,
|
pub algorithm: AlgorithmIdentifier<'a>,
|
||||||
subject_public_key: &'a [u8],
|
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>,
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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::Certificate as Asn1DerCertificate;
|
||||||
use crate::certificate::Version as Asn1DerVersion;
|
use crate::certificate::Version as Asn1DerVersion;
|
||||||
use crate::certificate::AlgorithmIdentifier as Asn1DerAlgId;
|
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::TryFrom;
|
||||||
use core::convert::TryInto;
|
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])> {
|
pub fn parse_asn1_der_object(bytes: &[u8]) -> IResult<&[u8], (u8, usize, &[u8])> {
|
||||||
let (rest, (tag, length)) = parse_asn1_der_header(bytes)?;
|
let (rest, (tag, length)) = parse_asn1_der_header(bytes)?;
|
||||||
let (rest, value) = take(length)(rest)?;
|
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 {
|
if tag_val != 0x02 {
|
||||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
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))
|
Ok((rest, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,8 +472,77 @@ pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
Ok((rest, value))
|
Ok((rest, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parser for Time Validity Structure
|
// Parser for Time Validity Sequence Structure (0x30)
|
||||||
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], Asn1DerValidity> {
|
||||||
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?;
|
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