Skip to content

Commit d0663a4

Browse files
committed
Convert all structs to Cow (#76)
1 parent d387316 commit d0663a4

10 files changed

+102
-64
lines changed

examples/print-cert.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn format_oid(oid: &Oid) -> String {
2323
fn print_x509_extension(oid: &Oid, ext: &X509Extension) {
2424
print!(" {}: ", format_oid(oid));
2525
print!(" Critical={}", ext.critical);
26-
print!(" len={}", ext.value.len());
26+
print!(" len={}", ext.value().len());
2727
println!();
2828
match ext.parsed_extension() {
2929
ParsedExtension::BasicConstraints(bc) => {

examples/print-crl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn print_authority_key_identifier(aki: &AuthorityKeyIdentifier, level: usize) {
3333
if aki.authority_cert_issuer.is_some() {
3434
unimplemented!();
3535
}
36-
if let Some(serial) = aki.authority_cert_serial {
36+
if let Some(serial) = &aki.authority_cert_serial {
3737
let mut s = serial
3838
.iter()
3939
.fold(String::with_capacity(3 * serial.len()), |a, b| {
@@ -76,7 +76,7 @@ fn print_x509_extension(oid: &Oid, ext: &X509Extension, level: usize) {
7676
x => {
7777
print!("{:indent$}{}:", "", format_oid(oid), indent = level);
7878
print!(" Critical={}", ext.critical);
79-
print!(" len={}", ext.value.len());
79+
print!(" len={}", ext.value().len());
8080
println!();
8181
println!(" {:indent$}{:?}", "", x, indent = level);
8282
}

src/certificate.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use der_parser::oid::Oid;
1616
use der_parser::*;
1717
use nom::Offset;
1818
use oid_registry::*;
19+
use std::borrow::Cow;
1920
use std::collections::HashMap;
2021

2122
/// An X.509 v3 Certificate.
@@ -179,7 +180,7 @@ impl<'a> X509Certificate<'a> {
179180
signature::UnparsedPublicKey::new(verification_alg, &spki.subject_public_key.data);
180181
// verify signature
181182
let sig = &self.signature_value.data;
182-
key.verify(self.tbs_certificate.raw, &sig)
183+
key.verify(&self.tbs_certificate.raw, &sig)
183184
.or(Err(X509Error::SignatureVerificationError))
184185
}
185186
}
@@ -218,8 +219,8 @@ pub struct TbsCertificate<'a> {
218219
pub issuer_uid: Option<UniqueIdentifier<'a>>,
219220
pub subject_uid: Option<UniqueIdentifier<'a>>,
220221
pub extensions: HashMap<Oid<'a>, X509Extension<'a>>,
221-
pub(crate) raw: &'a [u8],
222-
pub(crate) raw_serial: &'a [u8],
222+
pub(crate) raw: Cow<'a, [u8]>,
223+
pub(crate) raw_serial: Cow<'a, [u8]>,
223224
}
224225

225226
impl<'a> TbsCertificate<'a> {
@@ -267,8 +268,8 @@ impl<'a> TbsCertificate<'a> {
267268
subject_uid,
268269
extensions,
269270

270-
raw: &start_i[..len],
271-
raw_serial: serial.0,
271+
raw: Cow::Borrowed(&start_i[..len]),
272+
raw_serial: Cow::Borrowed(serial.0),
272273
};
273274
Ok((i, tbs))
274275
})(i)
@@ -352,7 +353,7 @@ impl<'a> TbsCertificate<'a> {
352353

353354
/// Get the raw bytes of the certificate serial number
354355
pub fn raw_serial(&self) -> &[u8] {
355-
self.raw_serial
356+
&self.raw_serial
356357
}
357358

358359
/// Get a formatted string of the certificate serial number, separated by ':'

src/certification_request.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use der_parser::*;
1414
use nom::Offset;
1515
#[cfg(feature = "verify")]
1616
use oid_registry::*;
17+
use std::borrow::Cow;
1718
use std::collections::HashMap;
1819

1920
#[derive(Debug, PartialEq)]
@@ -100,7 +101,7 @@ impl<'a> X509CertificationRequest<'a> {
100101
signature::UnparsedPublicKey::new(verification_alg, &spki.subject_public_key.data);
101102
// verify signature
102103
let sig = &self.signature_value.data;
103-
key.verify(self.certification_request_info.raw, &sig)
104+
key.verify(&self.certification_request_info.raw, &sig)
104105
.or(Err(X509Error::SignatureVerificationError))
105106
}
106107
}
@@ -111,7 +112,7 @@ pub struct X509CertificationRequestInfo<'a> {
111112
pub subject: X509Name<'a>,
112113
pub subject_pki: SubjectPublicKeyInfo<'a>,
113114
pub attributes: HashMap<Oid<'a>, X509CriAttribute<'a>>,
114-
pub raw: &'a [u8],
115+
pub raw: Cow<'a, [u8]>,
115116
}
116117

117118
impl<'a> X509CertificationRequestInfo<'a> {
@@ -145,7 +146,7 @@ impl<'a> X509CertificationRequestInfo<'a> {
145146
subject,
146147
subject_pki,
147148
attributes,
148-
raw: &start_i[..len],
149+
raw: Cow::Borrowed(&start_i[..len]),
149150
};
150151
Ok((i, tbs))
151152
})(i)

src/cri_attributes.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ use der_parser::oid::Oid;
1111
use nom::combinator::map_res;
1212
use nom::Err;
1313
use oid_registry::*;
14+
use std::borrow::Cow;
1415
use std::collections::HashMap;
1516

1617
/// Attributes for Certification Request
1718
#[derive(Debug, PartialEq)]
1819
pub struct X509CriAttribute<'a> {
1920
pub oid: Oid<'a>,
20-
pub value: &'a [u8],
21+
pub(crate) value: Cow<'a, [u8]>,
2122
pub(crate) parsed_attribute: ParsedCriAttribute<'a>,
2223
}
2324

@@ -34,13 +35,17 @@ impl<'a> X509CriAttribute<'a> {
3435
let (i, parsed_attribute) = crate::cri_attributes::parser::parse_attribute(i, &oid)?;
3536
let ext = X509CriAttribute {
3637
oid,
37-
value: &value_start[..value_start.len() - i.len()],
38+
value: Cow::Borrowed(&value_start[..value_start.len() - i.len()]),
3839
parsed_attribute,
3940
};
4041
Ok((i, ext))
4142
})(i)
4243
.map_err(|_| X509Error::InvalidAttributes.into())
4344
}
45+
46+
pub fn value(&'a self) -> &'a [u8] {
47+
&self.value
48+
}
4449
}
4550

4651
/// Section 3.1 of rfc 5272

src/extensions.rs

+43-26
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use nom::combinator::{all_consuming, complete, map_opt, map_res, opt};
1212
use nom::multi::{many0, many1};
1313
use nom::{exact, Err};
1414
use oid_registry::*;
15+
use std::borrow::Cow;
1516
use std::collections::HashMap;
1617
use std::fmt;
1718

@@ -24,7 +25,7 @@ pub struct X509Extension<'a> {
2425
/// An extension includes the boolean critical, with a default value of FALSE.
2526
pub critical: bool,
2627
/// Raw content of the extension
27-
pub value: &'a [u8],
28+
pub(crate) value: Cow<'a, [u8]>,
2829
pub(crate) parsed_extension: ParsedExtension<'a>,
2930
}
3031

@@ -92,7 +93,7 @@ impl<'a> X509Extension<'a> {
9293
let ext = X509Extension {
9394
oid,
9495
critical,
95-
value,
96+
value: Cow::Borrowed(value),
9697
parsed_extension,
9798
};
9899
Ok((i, ext))
@@ -109,11 +110,16 @@ impl<'a> X509Extension<'a> {
109110
X509Extension {
110111
oid,
111112
critical,
112-
value,
113+
value: Cow::Borrowed(value),
113114
parsed_extension,
114115
}
115116
}
116117

118+
/// Return the value bytes
119+
pub fn value(&'a self) -> &'a [u8] {
120+
&self.value
121+
}
122+
117123
/// Return the extension type or `UnsupportedExtension` if the extension is not implemented.
118124
pub fn parsed_extension(&self) -> &ParsedExtension<'a> {
119125
&self.parsed_extension
@@ -163,12 +169,12 @@ pub enum ParsedExtension<'a> {
163169
pub struct AuthorityKeyIdentifier<'a> {
164170
pub key_identifier: Option<KeyIdentifier<'a>>,
165171
pub authority_cert_issuer: Option<Vec<GeneralName<'a>>>,
166-
pub authority_cert_serial: Option<&'a [u8]>,
172+
pub authority_cert_serial: Option<Cow<'a, [u8]>>,
167173
}
168174

169175
#[derive(Debug, PartialEq)]
170176
pub struct CertificatePolicies<'a> {
171-
pub policies: HashMap<Oid<'a>, &'a [u8]>,
177+
pub policies: HashMap<Oid<'a>, Cow<'a, [u8]>>,
172178
}
173179

174180
/// Identifies whether the subject of the certificate is a CA, and the max validation depth.
@@ -179,7 +185,7 @@ pub struct BasicConstraints {
179185
}
180186

181187
#[derive(Debug, PartialEq)]
182-
pub struct KeyIdentifier<'a>(pub &'a [u8]);
188+
pub struct KeyIdentifier<'a>(pub Cow<'a, [u8]>);
183189

184190
#[derive(Debug, PartialEq)]
185191
pub struct KeyUsage {
@@ -355,20 +361,20 @@ pub struct SubjectAlternativeName<'a> {
355361
///
356362
/// String formats are not validated.
357363
pub enum GeneralName<'a> {
358-
OtherName(Oid<'a>, &'a [u8]),
364+
OtherName(Oid<'a>, Cow<'a, [u8]>),
359365
/// More or less an e-mail, the format is not checked.
360-
RFC822Name(&'a str),
366+
RFC822Name(Cow<'a, str>),
361367
/// A hostname, format is not checked.
362-
DNSName(&'a str),
368+
DNSName(Cow<'a, str>),
363369
// X400Address,
364370
/// RFC5280 defines several string types, we always try to parse as utf-8
365371
/// which is more or less a superset of the string types.
366372
DirectoryName(X509Name<'a>),
367373
// EDIPartyName { name_assigner: Option<&'a str>, party_name: &'a str },
368374
/// An uniform resource identifier. The format is not checked.
369-
URI(&'a str),
375+
URI(Cow<'a, str>),
370376
/// An ip address, provided as encoded.
371-
IPAddress(&'a [u8]),
377+
IPAddress(Cow<'a, [u8]>),
372378
RegisteredID(Oid<'a>),
373379
}
374380

@@ -552,19 +558,20 @@ pub(crate) mod parser {
552558
if len > rest.len() {
553559
return Err(nom::Err::Failure(BerError::ObjectTooShort));
554560
}
555-
fn ia5str<'a>(i: &'a [u8], hdr: DerObjectHeader) -> Result<&'a str, Err<BerError>> {
561+
fn ia5str<'a>(i: &'a [u8], hdr: DerObjectHeader) -> Result<Cow<'a, str>, Err<BerError>> {
556562
der_read_element_content_as(i, DerTag::Ia5String, hdr.len, hdr.is_constructed(), 0)?
557563
.1
558564
.into_bytes()
559565
.and_then(|s| std::str::from_utf8(s).map_err(|_| BerError::BerValueError))
566+
.map(Cow::Borrowed)
560567
.map_err(nom::Err::Failure)
561568
}
562569
let name = match hdr.tag.0 {
563570
0 => {
564571
// otherName SEQUENCE { OID, [0] explicit any defined by oid }
565572
let (any, oid) = parse_der_oid(rest)?;
566573
let oid = oid.as_oid_val().map_err(nom::Err::Failure)?;
567-
GeneralName::OtherName(oid, any)
574+
GeneralName::OtherName(oid, Cow::Borrowed(any))
568575
}
569576
1 => GeneralName::RFC822Name(ia5str(rest, hdr)?),
570577
2 => GeneralName::DNSName(ia5str(rest, hdr)?),
@@ -590,7 +597,7 @@ pub(crate) mod parser {
590597
.1
591598
.into_bytes()
592599
.map_err(nom::Err::Failure)?;
593-
GeneralName::IPAddress(ip)
600+
GeneralName::IPAddress(Cow::Borrowed(ip))
594601
}
595602
8 => {
596603
let oid = der_read_element_content_as(
@@ -756,7 +763,7 @@ pub(crate) mod parser {
756763
_hdr: DerObjectHeader<'_>,
757764
) -> IResult<&'a [u8], AuthorityKeyIdentifier<'a>, BerError> {
758765
let (i, key_identifier) = opt(complete(parse_der_tagged_implicit_g(0, |d, _, _| {
759-
Ok((&[], KeyIdentifier(d)))
766+
Ok((&[], KeyIdentifier(Cow::Borrowed(d))))
760767
})))(i)?;
761768
let (i, authority_cert_issuer) =
762769
opt(complete(parse_der_tagged_implicit_g(1, |d, _, _| {
@@ -766,7 +773,8 @@ pub(crate) mod parser {
766773
2,
767774
parse_der_content(DerTag::Integer),
768775
)))(i)?;
769-
let authority_cert_serial = authority_cert_serial.and_then(|o| o.into_bytes().ok());
776+
let authority_cert_serial =
777+
authority_cert_serial.and_then(|o| o.into_bytes().map(Cow::Borrowed).ok());
770778
let aki = AuthorityKeyIdentifier {
771779
key_identifier,
772780
authority_cert_issuer,
@@ -804,7 +812,7 @@ pub(crate) mod parser {
804812
.content
805813
.into_bytes()
806814
.or(Err(Err::Error(BerError::BerTypeError)))?;
807-
let ki = KeyIdentifier(id);
815+
let ki = KeyIdentifier(Cow::Borrowed(id));
808816
let ret = ParsedExtension::SubjectKeyIdentifier(ki);
809817
Ok((rest, ret))
810818
}
@@ -855,11 +863,12 @@ pub(crate) mod parser {
855863
//
856864
// PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
857865
fn parse_certificatepolicies(i: &[u8]) -> IResult<&[u8], ParsedExtension, BerError> {
858-
fn parse_policy_information(i: &[u8]) -> IResult<&[u8], (Oid, &[u8]), BerError> {
866+
type LocalPolicyInfo<'a> = (Oid<'a>, Cow<'a, [u8]>);
867+
fn parse_policy_information(i: &[u8]) -> IResult<&[u8], LocalPolicyInfo, BerError> {
859868
parse_der_sequence_defined_g(|content, _| {
860869
let (qualifier_set, oid) =
861870
map_res(parse_der_oid, |x: DerObject| x.as_oid_val())(content)?;
862-
Ok((&[], (oid, qualifier_set)))
871+
Ok((&[], (oid, Cow::Borrowed(qualifier_set))))
863872
})(i)
864873
}
865874
let (ret, mut policy_list) = parse_der_sequence_of_v(parse_policy_information)(i)?;
@@ -1024,11 +1033,14 @@ mod tests {
10241033
);
10251034
{
10261035
let alt_names = &tbs.subject_alternative_name().unwrap().1.general_names;
1027-
assert_eq!(alt_names[0], GeneralName::RFC822Name("[email protected]"));
1028-
assert_eq!(alt_names[1], GeneralName::URI("http://my.url.here/"));
1036+
assert_eq!(
1037+
alt_names[0],
1038+
GeneralName::RFC822Name("[email protected]".into())
1039+
);
1040+
assert_eq!(alt_names[1], GeneralName::URI("http://my.url.here/".into()));
10291041
assert_eq!(
10301042
alt_names[2],
1031-
GeneralName::IPAddress([192, 168, 7, 1].as_ref())
1043+
GeneralName::IPAddress(Cow::Borrowed(&[192, 168, 7, 1]))
10321044
);
10331045
assert_eq!(
10341046
format!(
@@ -1040,11 +1052,14 @@ mod tests {
10401052
),
10411053
"C=UK, O=My Organization, OU=My Unit, CN=My Name"
10421054
);
1043-
assert_eq!(alt_names[4], GeneralName::DNSName("localhost"));
1055+
assert_eq!(alt_names[4], GeneralName::DNSName("localhost".into()));
10441056
assert_eq!(alt_names[5], GeneralName::RegisteredID(oid!(1.2.90 .0)));
10451057
assert_eq!(
10461058
alt_names[6],
1047-
GeneralName::OtherName(oid!(1.2.3 .4), b"\xA0\x17\x0C\x15some other identifier")
1059+
GeneralName::OtherName(
1060+
oid!(1.2.3 .4),
1061+
Cow::Borrowed(b"\xA0\x17\x0C\x15some other identifier")
1062+
)
10481063
);
10491064
}
10501065

@@ -1055,10 +1070,12 @@ mod tests {
10551070
name_constraints.excluded_subtrees,
10561071
Some(vec![
10571072
GeneralSubtree {
1058-
base: GeneralName::IPAddress([192, 168, 0, 0, 255, 255, 0, 0].as_ref())
1073+
base: GeneralName::IPAddress(Cow::Borrowed(&[
1074+
192, 168, 0, 0, 255, 255, 0, 0
1075+
]))
10591076
},
10601077
GeneralSubtree {
1061-
base: GeneralName::RFC822Name("foo.com")
1078+
base: GeneralName::RFC822Name("foo.com".into())
10621079
},
10631080
])
10641081
);

0 commit comments

Comments
 (0)