diff --git a/examples/fakecert.rs b/examples/fakecert.rs index 5cd276e..f1f5b29 100644 --- a/examples/fakecert.rs +++ b/examples/fakecert.rs @@ -7,12 +7,13 @@ extern crate pkix; use pkix::pem::{der_to_pem, PEM_CERTIFICATE}; +use pkix::x509::TBS_CERTIFICATE_V3; #[path="../tests/fakes.rs"] pub mod fakes; fn main() { - let cert = fakes::cert_der(fakes::random_printable_string); + let cert = fakes::cert_der(fakes::random_printable_string, TBS_CERTIFICATE_V3); println!("{}", der_to_pem(&cert, PEM_CERTIFICATE)); } diff --git a/src/x509.rs b/src/x509.rs index 9b96976..6b1e483 100644 --- a/src/x509.rs +++ b/src/x509.rs @@ -52,7 +52,7 @@ impl BER #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct TbsCertificate { - // version: v3 + pub version: u8, pub serial: S, pub sigalg: A, pub issuer: Name, @@ -76,13 +76,17 @@ impl TbsCertificate { } } -const TBS_CERTIFICATE_V3: u8 = 2; +pub const TBS_CERTIFICATE_V1: u8 = 0; +pub const TBS_CERTIFICATE_V2: u8 = 1; +pub const TBS_CERTIFICATE_V3: u8 = 2; impl DerWrite for TbsCertificate { fn write(&self, writer: DERWriter) { writer.write_sequence(|writer| { - writer.next().write_tagged(Tag::context(0), |w| TBS_CERTIFICATE_V3.write(w)); + if self.version != TBS_CERTIFICATE_V1 { // default value + writer.next().write_tagged(Tag::context(0), |w| self.version.write(w)); + } self.serial.write(writer.next()); self.sigalg.write(writer.next()); self.issuer.write(writer.next()); @@ -108,10 +112,11 @@ impl DerWr impl BERDecodable for TbsCertificate { fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result { reader.read_sequence(|r| { - let version = r.next().read_tagged(Tag::context(0), |r| r.read_u8())?; - if version != TBS_CERTIFICATE_V3 { - return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); - } + let version = r.read_optional(|r| r.read_tagged(Tag::context(0), |r| r.read_u8()))?.unwrap_or(0); + match version { + TBS_CERTIFICATE_V1 | TBS_CERTIFICATE_V2 | TBS_CERTIFICATE_V3 => { /* known version */ } + _ => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } + }; let serial = S::decode_ber(r.next())?; let sigalg = A::decode_ber(r.next())?; let issuer = Name::decode_ber(r.next())?; @@ -123,6 +128,9 @@ impl::new(); @@ -143,7 +151,7 @@ impl Vec) })); CertificationRequest { - reqinfo: CertificationRequestInfo { - subject: - vec![(oid::description.clone(), - TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())), - (oid::dnQualifier.clone(), - TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), - spki: yasna::construct_der(|w| - w.write_sequence(|writer| { - writer.next().write_sequence(|writer| { - oid_rsa_encryption.write(writer.next()); - writer.next().write_null(); - }); - BitVec::from_bytes(&rsapubkey).write(writer.next()); - }) - ).into(), - attributes: vec![Attribute { - oid: oid::extensionRequest.clone(), - value: vec![exts.into()], - }], - }, - sigalg: RsaPkcs15(Sha256), - sig: BitVec::from_elem(8, false), - } + reqinfo: CertificationRequestInfo { + subject: + vec![(oid::description.clone(), + TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())), + (oid::dnQualifier.clone(), + TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), + spki: yasna::construct_der(|w| + w.write_sequence(|writer| { + writer.next().write_sequence(|writer| { + oid_rsa_encryption.write(writer.next()); + writer.next().write_null(); + }); + BitVec::from_bytes(&rsapubkey).write(writer.next()); + }) + ).into(), + attributes: vec![Attribute { + oid: oid::extensionRequest.clone(), + value: vec![exts.into()], + }], + }, + sigalg: RsaPkcs15(Sha256), + sig: BitVec::from_elem(8, false), + } } pub fn csr_der(get_random_printable_string: fn(usize) -> Vec) -> Vec { @@ -94,7 +94,7 @@ pub fn csr_der(get_random_printable_string: fn(usize) -> Vec) -> Vec { } -pub fn cert(get_random_printable_string: fn(usize) -> Vec) +pub fn cert(get_random_printable_string: fn(usize) -> Vec, version: u8) -> Certificate, DerSequence<'static>>, RsaPkcs15, BitVec> { let oid_rsa_encryption = ObjectIdentifier::from(vec![1, 2, 840, 113549, 1, 1, 1]); @@ -108,42 +108,49 @@ pub fn cert(get_random_printable_string: fn(usize) -> Vec) }) }); + let extensions = if version == TBS_CERTIFICATE_V3 { + vec![Extension { + oid: oid::basicConstraints.clone(), + critical: true, + value: vec![0x30, 0], + }] + } else { + vec![] + }; + Certificate { - tbscert: TbsCertificate { - serial: 0, - sigalg: RsaPkcs15(Sha256), - issuer: - vec![(oid::dnQualifier.clone(), - TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), - validity_notbefore: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(), - validity_notafter: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(), - subject: - vec![(oid::description.clone(), - TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())), - (oid::dnQualifier.clone(), - TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), - spki: yasna::construct_der(|w| - w.write_sequence(|writer| { - writer.next().write_sequence(|writer| { - oid_rsa_encryption.write(writer.next()); - writer.next().write_null(); - }); - BitVec::from_bytes(&rsapubkey).write(writer.next()); - }) - ).into(), - extensions: vec![Extension { - oid: oid::basicConstraints.clone(), - critical: true, - value: vec![0x30, 0], - }], - }, + tbscert: TbsCertificate { + version, + serial: 0, sigalg: RsaPkcs15(Sha256), - sig: BitVec::from_elem(8, false), - } + issuer: + vec![(oid::dnQualifier.clone(), + TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), + validity_notbefore: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(), + validity_notafter: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(), + subject: + vec![(oid::description.clone(), + TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())), + (oid::dnQualifier.clone(), + TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(), + spki: yasna::construct_der(|w| + w.write_sequence(|writer| { + writer.next().write_sequence(|writer| { + oid_rsa_encryption.write(writer.next()); + writer.next().write_null(); + }); + BitVec::from_bytes(&rsapubkey).write(writer.next()); + }) + ).into(), + extensions, + }, + sigalg: RsaPkcs15(Sha256), + sig: BitVec::from_elem(8, false), + } } -pub fn cert_der(get_random_printable_string: fn(usize) -> Vec) -> Vec { - yasna::construct_der(|w| cert(get_random_printable_string).write(w)) +pub fn cert_der(get_random_printable_string: fn(usize) -> Vec, version: u8) -> Vec { + yasna::construct_der(|w| cert(get_random_printable_string, version).write(w)) } pub fn enveloped_data_v2() -> EnvelopedDataV2 { @@ -171,7 +178,7 @@ pub fn fake_callback(_: &[u8]) -> Result, ()> { pub fn signed_data_v3(get_random_printable_string: fn(usize) -> Vec) -> SignedDataV3 { let enveloped_data: EnvelopedData = enveloped_data_v2().into(); let encapsulated_content: EncapsulatedContentInfo = enveloped_data.into(); - let cert = cert(get_random_printable_string); + let cert = cert(get_random_printable_string, TBS_CERTIFICATE_V3); let cert = yasna::construct_der(|w| cert.write(w)); let signer_key_id = vec![0; 20]; @@ -230,9 +237,61 @@ fn fake_csr() { assert_eq!(yasna::construct_der(|w| csr.write(w)), der); assert_eq!(yasna::parse_der(&der, |r| CertificationRequest::decode_ber(r)).unwrap(), csr); } +#[test] +fn fake_cert_v1() { + use yasna::BERDecodable; + + let der = vec![ + 0x30, 0x81, 0xfc, 0x30, 0x81, 0xe6, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x35, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, + 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4f, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0d, 0x0c, 0x0f, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x2a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x19, 0x00, 0x30, 0x16, 0x02, 0x11, 0x00, 0xa6, 0xe0, 0xd7, 0xc4, + 0xc4, 0xbf, 0xcf, 0x69, 0x63, 0x60, 0xca, 0x77, 0x3d, 0x00, 0xa2, 0xb1, 0x02, 0x01, 0x03, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00]; + + let cert = cert(deterministic_printable_string, pkix::x509::TBS_CERTIFICATE_V1); + assert_eq!(yasna::construct_der(|w| cert.write(w)), der); + assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert); +} + +#[test] +fn fake_cert_v2() { + use yasna::BERDecodable; + + let der = vec![ + 0x30, 0x82, 0x01, 0x01, 0x30, 0x81, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x35, 0x31, 0x33, + 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, + 0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4f, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0d, 0x0c, 0x0f, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, + 0x6b, 0x65, 0x79, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, + 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x2a, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x19, 0x00, 0x30, 0x16, 0x02, + 0x11, 0x00, 0xa6, 0xe0, 0xd7, 0xc4, 0xc4, 0xbf, 0xcf, 0x69, 0x63, 0x60, 0xca, 0x77, 0x3d, 0x00, 0xa2, + 0xb1, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x02, 0x00, 0x00]; + + let cert = cert(deterministic_printable_string, pkix::x509::TBS_CERTIFICATE_V2); + assert_eq!(yasna::construct_der(|w| cert.write(w)), der); + assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert); +} #[test] -fn fake_cert() { +fn fake_cert_v3() { use yasna::BERDecodable; let der = vec![ @@ -254,7 +313,7 @@ fn fake_cert() { 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00]; - let cert = cert(deterministic_printable_string); + let cert = cert(deterministic_printable_string, TBS_CERTIFICATE_V3); assert_eq!(yasna::construct_der(|w| cert.write(w)), der); assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert); } @@ -263,7 +322,7 @@ fn fake_cert() { fn no_extensions() { use yasna::BERDecodable; - let mut cert = cert(deterministic_printable_string); + let mut cert = cert(deterministic_printable_string, TBS_CERTIFICATE_V3); cert.tbscert.extensions = vec![]; let der = yasna::construct_der(|w| cert.write(w));