Skip to content

Commit 7772f32

Browse files
committed
Add support for reading and writing V1 and V2 TbsCertificate versions, in addition to V3
1 parent ee20d14 commit 7772f32

File tree

5 files changed

+154
-70
lines changed

5 files changed

+154
-70
lines changed

examples/fakecert.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
extern crate pkix;
88

99
use pkix::pem::{der_to_pem, PEM_CERTIFICATE};
10+
use pkix::x509::TBS_CERTIFICATE_V3;
1011

1112
#[path="../tests/fakes.rs"]
1213
pub mod fakes;
1314

1415
fn main() {
15-
let cert = fakes::cert_der(fakes::random_printable_string);
16+
let cert = fakes::cert_der(fakes::random_printable_string, TBS_CERTIFICATE_V3);
1617

1718
println!("{}", der_to_pem(&cert, PEM_CERTIFICATE));
1819
}

src/x509.rs

+32-8
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<T: BERDecodable, A: SignatureAlgorithm + BERDecodable, S: BERDecodable> BER
5252

5353
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
5454
pub struct TbsCertificate<S: Integer, A: SignatureAlgorithm, K> {
55-
// version: v3
55+
pub version: u8,
5656
pub serial: S,
5757
pub sigalg: A,
5858
pub issuer: Name,
@@ -76,13 +76,17 @@ impl<S: Integer, A: SignatureAlgorithm, K> TbsCertificate<S, A, K> {
7676
}
7777
}
7878

79-
const TBS_CERTIFICATE_V3: u8 = 2;
79+
pub const TBS_CERTIFICATE_V1: u8 = 0;
80+
pub const TBS_CERTIFICATE_V2: u8 = 1;
81+
pub const TBS_CERTIFICATE_V3: u8 = 2;
8082

8183
impl<S: DerWrite + Integer, A: DerWrite + SignatureAlgorithm, K: DerWrite> DerWrite
8284
for TbsCertificate<S, A, K> {
8385
fn write(&self, writer: DERWriter) {
8486
writer.write_sequence(|writer| {
85-
writer.next().write_tagged(Tag::context(0), |w| TBS_CERTIFICATE_V3.write(w));
87+
if self.version != TBS_CERTIFICATE_V1 { // default value
88+
writer.next().write_tagged(Tag::context(0), |w| self.version.write(w));
89+
}
8690
self.serial.write(writer.next());
8791
self.sigalg.write(writer.next());
8892
self.issuer.write(writer.next());
@@ -108,10 +112,11 @@ impl<S: DerWrite + Integer, A: DerWrite + SignatureAlgorithm, K: DerWrite> DerWr
108112
impl<S: BERDecodable + Integer, A: BERDecodable + SignatureAlgorithm, K: BERDecodable> BERDecodable for TbsCertificate<S, A, K> {
109113
fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result<Self> {
110114
reader.read_sequence(|r| {
111-
let version = r.next().read_tagged(Tag::context(0), |r| r.read_u8())?;
112-
if version != TBS_CERTIFICATE_V3 {
113-
return Err(ASN1Error::new(ASN1ErrorKind::Invalid));
114-
}
115+
let version = r.read_optional(|r| r.read_tagged(Tag::context(0), |r| r.read_u8()))?.unwrap_or(0);
116+
match version {
117+
TBS_CERTIFICATE_V1 | TBS_CERTIFICATE_V2 | TBS_CERTIFICATE_V3 => { /* known version */ }
118+
_ => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }
119+
};
115120
let serial = S::decode_ber(r.next())?;
116121
let sigalg = A::decode_ber(r.next())?;
117122
let issuer = Name::decode_ber(r.next())?;
@@ -123,6 +128,9 @@ impl<S: BERDecodable + Integer, A: BERDecodable + SignatureAlgorithm, K: BERDeco
123128
let subject = Name::decode_ber(r.next())?;
124129
let spki = K::decode_ber(r.next())?;
125130
let extensions = r.read_optional(|r| {
131+
if version != TBS_CERTIFICATE_V3 {
132+
return Err(ASN1Error::new(ASN1ErrorKind::Invalid));
133+
}
126134
r.read_tagged(Tag::context(3), |r| {
127135
r.read_sequence(|r| {
128136
let mut extensions = Vec::<Extension>::new();
@@ -143,7 +151,7 @@ impl<S: BERDecodable + Integer, A: BERDecodable + SignatureAlgorithm, K: BERDeco
143151
})
144152
})?.unwrap_or(vec![]);
145153

146-
Ok(TbsCertificate { serial, sigalg, issuer, validity_notbefore, validity_notafter,
154+
Ok(TbsCertificate { version, serial, sigalg, issuer, validity_notbefore, validity_notafter,
147155
subject, spki, extensions })
148156
})
149157
}
@@ -283,4 +291,20 @@ mod tests {
283291
test_encode_decode(&subject_alt_name, der);
284292
test_encode_decode(&issuer_alt_name, der);
285293
}
294+
295+
#[test]
296+
fn parse_v1_cert() {
297+
let der = include_bytes!("../tests/data/v1_cert.der");
298+
let cert = yasna::parse_der(der, |r| GenericCertificate::decode_ber(r)).unwrap();
299+
assert_eq!(cert.tbscert.version, TBS_CERTIFICATE_V1);
300+
assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
301+
}
302+
303+
#[test]
304+
fn parse_v3_cert() {
305+
let der = include_bytes!("../tests/data/v3_cert.der");
306+
let cert = yasna::parse_der(der, |r| GenericCertificate::decode_ber(r)).unwrap();
307+
assert_eq!(cert.tbscert.version, TBS_CERTIFICATE_V3);
308+
assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
309+
}
286310
}

tests/data/v1_cert.der

1.03 KB
Binary file not shown.

tests/data/v3_cert.der

1.04 KB
Binary file not shown.

tests/fakes.rs

+120-61
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use self::yasna::tags::{TAG_UTF8STRING, TAG_PRINTABLESTRING};
2020
use self::pkix::types::{DateTime, DerSequence, Attribute, Extension, RsaPkcs15, Sha256};
2121
use self::pkix::{DerWrite, oid};
2222
use self::pkix::pkcs10::{CertificationRequest, CertificationRequestInfo};
23-
use self::pkix::x509::{Certificate, TbsCertificate};
23+
use self::pkix::x509::{Certificate, TbsCertificate, TBS_CERTIFICATE_V3};
2424
use self::pkix::cms::*;
2525
use self::pkix::algorithms::*;
2626

@@ -64,37 +64,37 @@ pub fn csr(get_random_printable_string: fn(usize) -> Vec<u8>)
6464
}));
6565

6666
CertificationRequest {
67-
reqinfo: CertificationRequestInfo {
68-
subject:
69-
vec![(oid::description.clone(),
70-
TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())),
71-
(oid::dnQualifier.clone(),
72-
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
73-
spki: yasna::construct_der(|w|
74-
w.write_sequence(|writer| {
75-
writer.next().write_sequence(|writer| {
76-
oid_rsa_encryption.write(writer.next());
77-
writer.next().write_null();
78-
});
79-
BitVec::from_bytes(&rsapubkey).write(writer.next());
80-
})
81-
).into(),
82-
attributes: vec![Attribute {
83-
oid: oid::extensionRequest.clone(),
84-
value: vec![exts.into()],
85-
}],
86-
},
87-
sigalg: RsaPkcs15(Sha256),
88-
sig: BitVec::from_elem(8, false),
89-
}
67+
reqinfo: CertificationRequestInfo {
68+
subject:
69+
vec![(oid::description.clone(),
70+
TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())),
71+
(oid::dnQualifier.clone(),
72+
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
73+
spki: yasna::construct_der(|w|
74+
w.write_sequence(|writer| {
75+
writer.next().write_sequence(|writer| {
76+
oid_rsa_encryption.write(writer.next());
77+
writer.next().write_null();
78+
});
79+
BitVec::from_bytes(&rsapubkey).write(writer.next());
80+
})
81+
).into(),
82+
attributes: vec![Attribute {
83+
oid: oid::extensionRequest.clone(),
84+
value: vec![exts.into()],
85+
}],
86+
},
87+
sigalg: RsaPkcs15(Sha256),
88+
sig: BitVec::from_elem(8, false),
89+
}
9090
}
9191

9292
pub fn csr_der(get_random_printable_string: fn(usize) -> Vec<u8>) -> Vec<u8> {
9393
yasna::construct_der(|w| csr(get_random_printable_string).write(w))
9494
}
9595

9696

97-
pub fn cert(get_random_printable_string: fn(usize) -> Vec<u8>)
97+
pub fn cert(get_random_printable_string: fn(usize) -> Vec<u8>, version: u8)
9898
-> Certificate<TbsCertificate<i64, RsaPkcs15<Sha256>, DerSequence<'static>>, RsaPkcs15<Sha256>, BitVec>
9999
{
100100
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<u8>)
108108
})
109109
});
110110

111+
let extensions = if version == TBS_CERTIFICATE_V3 {
112+
vec![Extension {
113+
oid: oid::basicConstraints.clone(),
114+
critical: true,
115+
value: vec![0x30, 0],
116+
}]
117+
} else {
118+
vec![]
119+
};
120+
111121
Certificate {
112-
tbscert: TbsCertificate {
113-
serial: 0,
114-
sigalg: RsaPkcs15(Sha256),
115-
issuer:
116-
vec![(oid::dnQualifier.clone(),
117-
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
118-
validity_notbefore: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(),
119-
validity_notafter: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(),
120-
subject:
121-
vec![(oid::description.clone(),
122-
TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())),
123-
(oid::dnQualifier.clone(),
124-
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
125-
spki: yasna::construct_der(|w|
126-
w.write_sequence(|writer| {
127-
writer.next().write_sequence(|writer| {
128-
oid_rsa_encryption.write(writer.next());
129-
writer.next().write_null();
130-
});
131-
BitVec::from_bytes(&rsapubkey).write(writer.next());
132-
})
133-
).into(),
134-
extensions: vec![Extension {
135-
oid: oid::basicConstraints.clone(),
136-
critical: true,
137-
value: vec![0x30, 0],
138-
}],
139-
},
122+
tbscert: TbsCertificate {
123+
version,
124+
serial: 0,
140125
sigalg: RsaPkcs15(Sha256),
141-
sig: BitVec::from_elem(8, false),
142-
}
126+
issuer:
127+
vec![(oid::dnQualifier.clone(),
128+
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
129+
validity_notbefore: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(),
130+
validity_notafter: DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(),
131+
subject:
132+
vec![(oid::description.clone(),
133+
TaggedDerValue::from_tag_and_bytes(TAG_UTF8STRING, b"Known keys only".to_vec())),
134+
(oid::dnQualifier.clone(),
135+
TaggedDerValue::from_tag_and_bytes(TAG_PRINTABLESTRING, get_random_printable_string(42)))].into(),
136+
spki: yasna::construct_der(|w|
137+
w.write_sequence(|writer| {
138+
writer.next().write_sequence(|writer| {
139+
oid_rsa_encryption.write(writer.next());
140+
writer.next().write_null();
141+
});
142+
BitVec::from_bytes(&rsapubkey).write(writer.next());
143+
})
144+
).into(),
145+
extensions,
146+
},
147+
sigalg: RsaPkcs15(Sha256),
148+
sig: BitVec::from_elem(8, false),
149+
}
143150
}
144151

145-
pub fn cert_der(get_random_printable_string: fn(usize) -> Vec<u8>) -> Vec<u8> {
146-
yasna::construct_der(|w| cert(get_random_printable_string).write(w))
152+
pub fn cert_der(get_random_printable_string: fn(usize) -> Vec<u8>, version: u8) -> Vec<u8> {
153+
yasna::construct_der(|w| cert(get_random_printable_string, version).write(w))
147154
}
148155

149156
pub fn enveloped_data_v2() -> EnvelopedDataV2 {
@@ -171,7 +178,7 @@ pub fn fake_callback(_: &[u8]) -> Result<Vec<u8>, ()> {
171178
pub fn signed_data_v3(get_random_printable_string: fn(usize) -> Vec<u8>) -> SignedDataV3 {
172179
let enveloped_data: EnvelopedData = enveloped_data_v2().into();
173180
let encapsulated_content: EncapsulatedContentInfo = enveloped_data.into();
174-
let cert = cert(get_random_printable_string);
181+
let cert = cert(get_random_printable_string, TBS_CERTIFICATE_V3);
175182
let cert = yasna::construct_der(|w| cert.write(w));
176183
let signer_key_id = vec![0; 20];
177184

@@ -230,9 +237,61 @@ fn fake_csr() {
230237
assert_eq!(yasna::construct_der(|w| csr.write(w)), der);
231238
assert_eq!(yasna::parse_der(&der, |r| CertificationRequest::decode_ber(r)).unwrap(), csr);
232239
}
240+
#[test]
241+
fn fake_cert_v1() {
242+
use yasna::BERDecodable;
243+
244+
let der = vec![
245+
0x30, 0x81, 0xfc, 0x30, 0x81, 0xe6, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
246+
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x35, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04,
247+
0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65,
248+
0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73,
249+
0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30,
250+
0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31,
251+
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4f, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
252+
0x55, 0x04, 0x0d, 0x0c, 0x0f, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x6f,
253+
0x6e, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73,
254+
0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74,
255+
0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74,
256+
0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x2a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
257+
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x19, 0x00, 0x30, 0x16, 0x02, 0x11, 0x00, 0xa6, 0xe0, 0xd7, 0xc4,
258+
0xc4, 0xbf, 0xcf, 0x69, 0x63, 0x60, 0xca, 0x77, 0x3d, 0x00, 0xa2, 0xb1, 0x02, 0x01, 0x03, 0x30, 0x0d,
259+
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00];
260+
261+
let cert = cert(deterministic_printable_string, pkix::x509::TBS_CERTIFICATE_V1);
262+
assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
263+
assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert);
264+
}
265+
266+
#[test]
267+
fn fake_cert_v2() {
268+
use yasna::BERDecodable;
269+
270+
let der = vec![
271+
0x30, 0x82, 0x01, 0x01, 0x30, 0x81, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x30, 0x0d,
272+
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x35, 0x31, 0x33,
273+
0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74,
274+
0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74,
275+
0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65,
276+
0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
277+
0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4f,
278+
0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0d, 0x0c, 0x0f, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x20,
279+
0x6b, 0x65, 0x79, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04,
280+
0x2e, 0x13, 0x2a, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65,
281+
0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73,
282+
0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x30, 0x2a, 0x30, 0x0d, 0x06, 0x09,
283+
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x19, 0x00, 0x30, 0x16, 0x02,
284+
0x11, 0x00, 0xa6, 0xe0, 0xd7, 0xc4, 0xc4, 0xbf, 0xcf, 0x69, 0x63, 0x60, 0xca, 0x77, 0x3d, 0x00, 0xa2,
285+
0xb1, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
286+
0x05, 0x00, 0x03, 0x02, 0x00, 0x00];
287+
288+
let cert = cert(deterministic_printable_string, pkix::x509::TBS_CERTIFICATE_V2);
289+
assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
290+
assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert);
291+
}
233292

234293
#[test]
235-
fn fake_cert() {
294+
fn fake_cert_v3() {
236295
use yasna::BERDecodable;
237296

238297
let der = vec![
@@ -254,7 +313,7 @@ fn fake_cert() {
254313
0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
255314
0x0b, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00];
256315

257-
let cert = cert(deterministic_printable_string);
316+
let cert = cert(deterministic_printable_string, TBS_CERTIFICATE_V3);
258317
assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
259318
assert_eq!(yasna::parse_der(&der, |r| Certificate::decode_ber(r)).unwrap(), cert);
260319
}
@@ -263,7 +322,7 @@ fn fake_cert() {
263322
fn no_extensions() {
264323
use yasna::BERDecodable;
265324

266-
let mut cert = cert(deterministic_printable_string);
325+
let mut cert = cert(deterministic_printable_string, TBS_CERTIFICATE_V3);
267326
cert.tbscert.extensions = vec![];
268327

269328
let der = yasna::construct_der(|w| cert.write(w));

0 commit comments

Comments
 (0)