Refactor, still broken, but moving towards not broken.

This commit is contained in:
2018-01-16 17:48:58 -08:00
parent 63be0eaef1
commit f4b8c7e945
18 changed files with 1670 additions and 522 deletions

View File

@@ -5,12 +5,173 @@ extern crate num;
extern crate quickcheck;
#[macro_use]
extern crate simple_asn1;
extern crate simple_dsa;
extern crate simple_rsa;
mod algident;
mod atv;
mod error;
mod misc;
mod name;
mod publickey;
mod validity;
use algident::AlgorithmIdentifier;
use atv::InfoBlock;
use error::X509ParseError;
use misc::{X509Serial,X509Version};
use publickey::X509PublicKey;
use simple_asn1::{ASN1Block,FromASN1};
use validity::Validity;
/*******************************************************************************
*
* The actual certificate data type and methods
*
******************************************************************************/
/// The type of an X.509 certificate.
#[derive(Debug)]
pub struct Certificate {
pub version: X509Version,
pub serial: X509Serial,
pub signature_alg: AlgorithmIdentifier,
pub issuer: InfoBlock,
pub subject: InfoBlock,
pub validity: Validity,
pub subject_key: X509PublicKey,
pub extensions: Vec<()>
}
fn decode_certificate(x: &ASN1Block)
-> Result<Certificate,X509ParseError>
{
//
// TBSCertificate ::= SEQUENCE {
// version [0] Version DEFAULT v1,
// serialNumber CertificateSerialNumber,
// signature AlgorithmIdentifier,
// issuer Name,
// validity Validity,
// subject Name,
// subjectPublicKeyInfo SubjectPublicKeyInfo,
// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// extensions [3] Extensions OPTIONAL
// -- If present, version MUST be v3 -- }
//
println!("x: {:?}", x);
match x {
&ASN1Block::Sequence(_, _, ref b0) => {
let (version, b1) = X509Version::from_asn1(b0)?;
println!("version: {:?}", version);
let (serial, b2) = X509Serial::from_asn1(b1)?;
println!("serial: {:?}", serial);
let (ident, b3) = AlgorithmIdentifier::from_asn1(b2)?;
println!("ident: {:?}", ident);
let (issuer, b4) = InfoBlock::from_asn1(b3)?;
println!("issuer: {:?}", issuer);
let (validity, b5) = Validity::from_asn1(b4)?;
println!("validity: {:?}", validity);
let (subject, b6) = InfoBlock::from_asn1(b5)?;
println!("subject: {:?}", subject);
let (subkey, b7) = X509PublicKey::from_asn1(b6)?;
println!("subkey: {:?}", subkey);
println!("REMAINDER: {:?}", b7);
Ok(Certificate {
version: version,
serial: serial,
signature_alg: ident,
issuer: issuer,
subject: subject,
validity: validity,
subject_key: subkey,
extensions: vec![]
})
}
_ =>
Err(X509ParseError::IllFormedCertificateInfo)
}
}
/*******************************************************************************
*
* X.509 parsing routines
*
******************************************************************************/
fn parse_x509(blocks: &[ASN1Block], buffer: &[u8])
-> Result<Certificate,X509ParseError>
{
match blocks.first() {
None =>
Err(X509ParseError::NotEnoughData),
Some(&ASN1Block::Sequence(_, _, ref x)) => {
let cert = decode_certificate(&x[0])?;
println!("cert: {:?}", cert);
Ok(cert)
}
Some(_) =>
Err(X509ParseError::IllFormedEverything)
}
}
/*******************************************************************************
*
* Testing is for winners!
*
******************************************************************************/
#[cfg(test)]
mod tests {
use simple_asn1::from_der;
use std::fs::File;
use std::io::Read;
use super::*;
fn can_parse(f: &str) -> Result<Certificate,X509ParseError> {
let mut fd = File::open(f).unwrap();
let mut buffer = Vec::new();
let _amt = fd.read_to_end(&mut buffer);
println!("_amt: {:?}", _amt);
let asn1: Vec<ASN1Block> = from_der(&buffer[..])?;
parse_x509(&asn1, &buffer)
}
#[test]
fn rsa_tests() {
assert!(can_parse("test/rsa2048-1.der").is_ok());
assert!(can_parse("test/rsa2048-2.der").is_ok());
assert!(can_parse("test/rsa4096-1.der").is_ok());
assert!(can_parse("test/rsa4096-2.der").is_ok());
assert!(can_parse("test/rsa4096-3.der").is_ok());
}
#[test]
fn dsa_tests() {
assert!(can_parse("test/dsa2048-1.der").is_ok());
assert!(can_parse("test/dsa2048-2.der").is_ok());
assert!(can_parse("test/dsa3072-1.der").is_ok());
assert!(can_parse("test/dsa3072-2.der").is_ok());
}
// #[test]
fn ecc_tests() {
assert!(can_parse("test/ec384-1.der").is_ok());
assert!(can_parse("test/ec384-2.der").is_ok());
assert!(can_parse("test/ec384-3.der").is_ok());
}
}
/*
use chrono::{DateTime,Utc};
use num::{BigUint,ToPrimitive};
use simple_asn1::{ASN1Block,ASN1Class,FromASN1,FromASN1WithBody,OID,ToASN1};
use simple_asn1::{ASN1DecodeErr,ASN1EncodeErr,der_decode};
use simple_dsa::{DSAPublicKey};
use simple_rsa::{RSAPublicKey,RSAError,SigningHash,
SIGNING_HASH_SHA1, SIGNING_HASH_SHA224, SIGNING_HASH_SHA256,
SIGNING_HASH_SHA384, SIGNING_HASH_SHA512};
@@ -19,7 +180,14 @@ use simple_rsa::{RSAPublicKey,RSAError,SigningHash,
enum HashAlgorithm { None, MD2, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }
#[derive(Clone,Debug,PartialEq)]
enum PubKeyAlgorithm { RSA, RSAPSS, DSA, EC, DH, Unknown(OID) }
enum PubKeyAlgorithm {
RSA,
RSAPSS,
DSA(BigUint,BigUint,BigUint),
EC,
DH,
Unknown(OID)
}
#[derive(Debug)]
enum X509ParseError {
@@ -28,14 +196,15 @@ enum X509ParseError {
NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation,
NoValueForName, UnknownAttrTypeValue, IllegalStringValue, NoValidityInfo,
ImproperValidityInfo, NoSubjectPublicKeyInfo, ImproperSubjectPublicKeyInfo,
BadPublicKeyAlgorithm, UnsupportedPublicKey, InvalidRSAKey,
BadPublicKeyAlgorithm, UnsupportedPublicKey, InvalidRSAKey, InvalidDSAInfo,
UnsupportedExtension, UnexpectedNegativeNumber, MissingNumber,
NoSignatureFound, UnsupportedSignature, SignatureFailed
}
#[derive(Clone,Debug,PartialEq)]
enum X509PublicKey {
RSA(RSAPublicKey)
DSA(DSAPublicKey),
RSA(RSAPublicKey),
}
impl From<ASN1DecodeErr> for X509ParseError {
@@ -126,152 +295,7 @@ impl FromASN1 for SignatureAlgorithm {
Some((x, rest)) => {
match x {
&ASN1Block::ObjectIdentifier(_, _, ref oid) => {
if oid == oid!(1,2,840,113549,1,1,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::None,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,5) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA1,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,4) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::MD5,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,2) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::MD2,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,11) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA256,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,12) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA384,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,13) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA512,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,14) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA224,
key_alg: PubKeyAlgorithm::RSA
}, rest));
}
if oid == oid!(1,2,840,10040,4,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::None,
key_alg: PubKeyAlgorithm::DSA
}, rest));
}
if oid == oid!(1,2,840,10040,4,3) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA1,
key_alg: PubKeyAlgorithm::DSA
}, rest));
}
if oid == oid!(1,2,840,10045,2,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::None,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,10045,4,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA1,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,10045,4,3,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA224,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,10045,4,3,2) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA256,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,10045,4,3,3) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA384,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,10045,4,3,4) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA512,
key_alg: PubKeyAlgorithm::EC
}, rest));
}
if oid == oid!(1,2,840,113549,1,1,10) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::None,
key_alg: PubKeyAlgorithm::RSAPSS
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,2,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA256,
key_alg: PubKeyAlgorithm::RSAPSS
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,2,2) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA384,
key_alg: PubKeyAlgorithm::RSAPSS
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,2,3) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA512,
key_alg: PubKeyAlgorithm::RSAPSS
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,2,4) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA224,
key_alg: PubKeyAlgorithm::RSAPSS
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,3,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA224,
key_alg: PubKeyAlgorithm::DSA
}, rest));
}
if oid == oid!(2,16,840,1,101,3,4,3,2) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::SHA256,
key_alg: PubKeyAlgorithm::DSA
}, rest));
}
if oid == oid!(1,2,840,10046,2,1) {
return Ok((SignatureAlgorithm {
hash_alg: HashAlgorithm::None,
key_alg: PubKeyAlgorithm::DH
}, rest));
}
Err(X509ParseError::ItemNotFound)
}
}
_ =>
Err(X509ParseError::ItemNotFound)
}
@@ -280,6 +304,21 @@ impl FromASN1 for SignatureAlgorithm {
}
}
fn decode_dsa_info(vs: &[ASN1Block])
-> Result<(BigUint, BigUint, BigUint), X509ParseError>
{
match vs.split_first() {
Some((&ASN1Block::Sequence(_, _, ref info), rest)) => {
let p = decode_biguint(&info[0])?;
let q = decode_biguint(&info[1])?;
let g = decode_biguint(&info[2])?;
Ok((p, q, g))
}
_ =>
Err(X509ParseError::InvalidDSAInfo)
}
}
#[derive(Clone,Debug,PartialEq)]
pub enum SigAlgEncodeErr {
ASN1Problem(ASN1EncodeErr),
@@ -441,72 +480,25 @@ fn signing_hash(a: HashAlgorithm)
}
}
fn get_tbs_certificate(x: &ASN1Block)
-> Result<Certificate,X509ParseError>
{
match x {
&ASN1Block::Sequence(_, _, ref v0) => {
// TBSCertificate ::= SEQUENCE {
// version [0] Version DEFAULT v1,
let (version, v1) = get_version(v0)?;
// serialNumber CertificateSerialNumber,
let (serial, v2) = get_serial(v1)?;
// signature AlgorithmIdentifier,
let (algo, v3) = get_signature_info(v2)?;
// issuer Name,
let (issuer, v4) = get_name_data(v3)?;
// validity Validity,
let (validity, v5) = get_validity_data(v4)?;
// subject Name,
let (subject, v6) = get_name_data(v5)?;
// subjectPublicKeyInfo SubjectPublicKeyInfo,
let (subpki, v7) = get_subject_pki(v6)?;
if (version < 3) && !v7.is_empty() {
return Err(X509ParseError::UnsupportedExtension)
}
// FIXME: Support v3 extensions
if !v7.is_empty() {
return Err(X509ParseError::UnsupportedExtension)
// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// extensions [3] Extensions OPTIONAL
// -- If present, version MUST be v3 -- }
//
}
Ok(Certificate{
version: version,
serial: serial,
signature_alg: algo,
issuer: issuer,
subject: subject,
validity: validity,
subject_key: subpki,
extensions: vec![]
})
}
_ =>
Err(X509ParseError::IllegalFormat)
}
}
fn get_signature_alg(x: &ASN1Block)
-> Result<SignatureAlgorithm,X509ParseError>
{
// AlgorithmIdentifier ::= SEQUENCE {
// algorithm OBJECT IDENTIFIER,
// parameters ANY DEFINED BY algorithm OPTIONAL }
println!("get_signature_alg {:?}", x);
match x {
&ASN1Block::Sequence(_, _, ref v) if v.len() == 2 => {
&ASN1Block::Sequence(_, _, ref v) => {
// initially there was a length check on v as a side condition
// for this case, but it caused unexpected problems and I took
// it out.
let (alg, _) = SignatureAlgorithm::from_asn1(v)?;
Ok(alg)
}
_ =>
_ => {
println!("Pattern match failed?!");
Err(X509ParseError::IllegalFormat)
}
}
}
@@ -558,6 +550,7 @@ fn get_signature_info(bs: &[ASN1Block])
{
match bs.split_first() {
Some((x, rest)) => {
println!("x: {:?}", x);
let alg = get_signature_alg(&x)?;
Ok((alg, rest))
}
@@ -566,322 +559,6 @@ fn get_signature_info(bs: &[ASN1Block])
}
}
#[derive(Clone,Debug,PartialEq)]
struct InfoBlock {
name: String,
surname: String,
given_name: String,
initials: String,
generation_qualifier: String,
common_name: String,
locality: String,
state_province: String,
organization: String,
unit: String,
title: String,
dn_qualifier: String,
country: String,
serial_number: String,
pseudonym: String,
domain_component: String,
email: String
}
fn empty_block() -> InfoBlock {
InfoBlock {
name: "".to_string(),
surname: "".to_string(),
given_name: "".to_string(),
initials: "".to_string(),
generation_qualifier: "".to_string(),
common_name: "".to_string(),
locality: "".to_string(),
state_province: "".to_string(),
organization: "".to_string(),
unit: "".to_string(),
title: "".to_string(),
dn_qualifier: "".to_string(),
country: "".to_string(),
serial_number: "".to_string(),
pseudonym: "".to_string(),
domain_component: "".to_string(),
email: "".to_string()
}
}
fn get_name_data(bs: &[ASN1Block])
-> Result<(InfoBlock,&[ASN1Block]),X509ParseError>
{
match bs.split_first() {
Some((x,rest)) => {
match x {
// Name ::= CHOICE { -- only one possibility for now --
// rdnSequence RDNSequence }
//
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
&ASN1Block::Sequence(_, _, ref items) => {
// RelativeDistinguishedName ::=
// SET SIZE (1..MAX) OF AttributeTypeAndValue
let mut iblock = empty_block();
for item in items.iter() {
match item {
&ASN1Block::Set(_, _, ref info) => {
for atv in info.iter() {
parse_attr_type_val(&atv, &mut iblock)?;
}
}
_ =>
return Err(X509ParseError::IllFormedNameInformation)
}
}
Ok((iblock, rest))
}
_ =>
Err(X509ParseError::NoNameInformation)
}
}
_ =>
Err(X509ParseError::NoNameInformation)
}
}
fn parse_attr_type_val(val: &ASN1Block, iblock: &mut InfoBlock)
-> Result<(),X509ParseError>
{
match val {
// AttributeTypeAndValue ::= SEQUENCE {
// type AttributeType,
// value AttributeValue }
&ASN1Block::Sequence(_, _, ref oidval) => {
match oidval.split_first() {
// AttributeType ::= OBJECT IDENTIFIER
Some((&ASN1Block::ObjectIdentifier(_, _, ref oid), rest)) => {
match rest.first() {
// AttributeValue ::= ANY -- DEFINED BY AttributeType
Some(val) =>
process_atv(oid, val, iblock),
None =>
Err(X509ParseError::NoValueForName)
}
}
_ =>
Err(X509ParseError::IllFormedNameInformation)
}
}
_ =>
Err(X509ParseError::IllFormedNameInformation)
}
}
fn process_atv(oid: &OID, val: &ASN1Block, iblock: &mut InfoBlock)
-> Result<(),X509ParseError>
{
//-- Arc for standard naming attributes
//
//id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
//
//-- Naming attributes of type X520name
//
//id-at-name AttributeType ::= { id-at 41 }
if oid == oid!(2,5,4,41) {
iblock.name = get_string_value(val)?;
return Ok(());
}
//id-at-surname AttributeType ::= { id-at 4 }
if oid == oid!(2,5,4,4) {
iblock.surname = get_string_value(val)?;
return Ok(());
}
//id-at-givenName AttributeType ::= { id-at 42 }
if oid == oid!(2,5,4,42) {
iblock.given_name = get_string_value(val)?;
return Ok(());
}
//id-at-initials AttributeType ::= { id-at 43 }
if oid == oid!(2,5,4,43) {
iblock.initials = get_string_value(val)?;
return Ok(());
}
//id-at-generationQualifier AttributeType ::= { id-at 44 }
if oid == oid!(2,5,4,44) {
iblock.generation_qualifier = get_string_value(val)?;
return Ok(());
}
//
//-- Naming attributes of type X520CommonName
//
//id-at-commonName AttributeType ::= { id-at 3 }
if oid == oid!(2,5,4,3) {
iblock.common_name = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520LocalityName
//
//id-at-localityName AttributeType ::= { id-at 7 }
if oid == oid!(2,5,4,7) {
iblock.locality = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520StateOrProvinceName
//
//id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
if oid == oid!(2,5,4,8) {
iblock.state_province = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520OrganizationName
//
//id-at-organizationName AttributeType ::= { id-at 10 }
if oid == oid!(2,5,4,10) {
iblock.organization = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520OrganizationalUnitName
//
//id-at-organizationalUnitName AttributeType ::= { id-at 11 }
if oid == oid!(2,5,4,11) {
iblock.unit = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520Title
//
//id-at-title AttributeType ::= { id-at 12 }
if oid == oid!(2,5,4,12) {
iblock.title = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type X520dnQualifier
//
//id-at-dnQualifier AttributeType ::= { id-at 46 }
//
//X520dnQualifier ::= PrintableString
if oid == oid!(2,5,4,46) {
iblock.dn_qualifier = get_printable_string_value(val)?;
return Ok(());
}
//
//-- Naming attributes of type X520countryName (digraph from IS 3166)
//
//id-at-countryName AttributeType ::= { id-at 6 }
//
//X520countryName ::= PrintableString (SIZE (2))
if oid == oid!(2,5,4,6) {
iblock.country = get_printable_string_value(val)?;
if iblock.country.len() != 2 {
return Err(X509ParseError::IllegalStringValue);
}
return Ok(());
}
//
//-- Naming attributes of type X520SerialNumber
//
//id-at-serialNumber AttributeType ::= { id-at 5 }
//
//X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
if oid == oid!(2,5,4,5) {
iblock.serial_number = get_printable_string_value(val)?;
return Ok(());
}
//
//-- Naming attributes of type X520Pseudonym
//
//id-at-pseudonym AttributeType ::= { id-at 65 }
if oid == oid!(2,5,4,65) {
iblock.pseudonym = get_string_value(val)?;
return Ok(());
}
//-- Naming attributes of type DomainComponent (from RFC 4519)
//
//id-domainComponent AttributeType ::= { 0 9 2342 19200300 100 1 25 }
//
//DomainComponent ::= IA5String
if oid == oid!(0,9,2342,19200300,100,1,25) {
iblock.domain_component = get_ia5_string_value(val)?;
return Ok(());
}
//-- Legacy attributes
//
//pkcs-9 OBJECT IDENTIFIER ::=
// { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
//
//id-emailAddress AttributeType ::= { pkcs-9 1 }
//
//EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
if oid == oid!(1,2,840,113549,1,9,1) {
iblock.email = get_ia5_string_value(val)?;
return Ok(());
}
Err(X509ParseError::UnknownAttrTypeValue)
}
fn get_string_value(a: &ASN1Block) -> Result<String,X509ParseError>
{
match a {
&ASN1Block::TeletexString(_,_,ref v) => Ok(v.clone()),
&ASN1Block::PrintableString(_,_,ref v) => Ok(v.clone()),
&ASN1Block::UniversalString(_,_,ref v) => Ok(v.clone()),
&ASN1Block::UTF8String(_,_,ref v) => Ok(v.clone()),
&ASN1Block::BMPString(_,_,ref v) => Ok(v.clone()),
_ =>
Err(X509ParseError::IllegalStringValue)
}
}
fn get_printable_string_value(a: &ASN1Block) -> Result<String,X509ParseError>
{
match a {
&ASN1Block::PrintableString(_,_,ref v) => Ok(v.clone()),
_ =>
Err(X509ParseError::IllegalStringValue)
}
}
fn get_ia5_string_value(a: &ASN1Block) -> Result<String,X509ParseError>
{
match a {
&ASN1Block::IA5String(_,_,ref v) => Ok(v.clone()),
_ =>
Err(X509ParseError::IllegalStringValue)
}
}
#[derive(Clone,Debug,PartialEq)]
struct Validity {
not_before: DateTime<Utc>,
not_after: DateTime<Utc>
}
fn get_validity_data(bs: &[ASN1Block])
-> Result<(Validity,&[ASN1Block]),X509ParseError>
{
match bs.split_first() {
// Validity ::= SEQUENCE {
// notBefore Time,
// notAfter Time }
Some((&ASN1Block::Sequence(_, _, ref valxs), rest)) => {
if valxs.len() != 2 {
return Err(X509ParseError::ImproperValidityInfo);
}
let nb = get_time(&valxs[0])?;
let na = get_time(&valxs[1])?;
Ok((Validity{ not_before: nb, not_after: na }, rest))
}
_ =>
Err(X509ParseError::NoValidityInfo)
}
}
fn get_time(b: &ASN1Block) -> Result<DateTime<Utc>, X509ParseError> {
match b {
&ASN1Block::UTCTime(_, _, v) => Ok(v.clone()),
&ASN1Block::GeneralizedTime(_, _, v) => Ok(v.clone()),
_ =>
Err(X509ParseError::ImproperValidityInfo)
}
}
fn get_subject_pki(b: &[ASN1Block])
-> Result<(X509PublicKey, &[ASN1Block]), X509ParseError>
{
@@ -890,6 +567,7 @@ fn get_subject_pki(b: &[ASN1Block])
// algorithm AlgorithmIdentifier,
// subjectPublicKey BIT STRING }
Some((&ASN1Block::Sequence(_, _, ref info), rest)) => {
println!("get_subject_pki {:?}", info);
if info.len() != 2 {
return Err(X509ParseError::ImproperSubjectPublicKeyInfo)
}
@@ -907,6 +585,9 @@ fn get_subject_pki(b: &[ASN1Block])
Ok((X509PublicKey::RSA(key), rest))
}
_ => {
let key = get_dsa_public_key(&info[1])?;
println!("key alg: {:?}", alginfo.key_alg);
println!("info: {:?}", info);
Err(X509ParseError::UnsupportedPublicKey)
}
}
@@ -928,9 +609,20 @@ fn get_rsa_public_key(b: &ASN1Block)
}
}
fn get_dsa_public_key(b: &ASN1Block)
-> Result<DSAPublicKey, X509ParseError>
{
match b {
&ASN1Block::BitString(_, _, size, ref vec) if size % 8 == 0 => {
unimplemented!();
}
_ =>
Err(X509ParseError::InvalidRSAKey)
}
}
#[cfg(test)]
mod tests {
use quickcheck::{Arbitrary,Gen};
use simple_asn1::{der_decode,der_encode};
use std::fs::File;
use std::io::Read;
@@ -941,7 +633,9 @@ mod tests {
match g.gen::<u8>() % 6 {
0 => PubKeyAlgorithm::RSA,
1 => PubKeyAlgorithm::RSAPSS,
2 => PubKeyAlgorithm::DSA,
2 => {
PubKeyAlgorithm::DSA,
}
3 => PubKeyAlgorithm::EC,
4 => PubKeyAlgorithm::DH,
5 => {
@@ -1099,5 +793,13 @@ mod tests {
assert!(can_parse("test/rsa4096-1.der").is_ok());
assert!(can_parse("test/rsa4096-2.der").is_ok());
assert!(can_parse("test/rsa4096-3.der").is_ok());
assert!(can_parse("test/dsa2048-1.der").is_ok());
assert!(can_parse("test/dsa2048-2.der").is_ok());
assert!(can_parse("test/dsa3072-1.der").is_ok());
assert!(can_parse("test/dsa3072-2.der").is_ok());
assert!(can_parse("test/ec384-1.der").is_ok());
assert!(can_parse("test/ec384-2.der").is_ok());
assert!(can_parse("test/ec384-3.der").is_ok());
}
}
*/