diff --git a/Cargo.toml b/Cargo.toml index 4be84684..28a5601e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ license-file = "LICENSE" name = "webpki" readme = "README.md" repository = "https://github.com/briansmith/webpki" -version = "0.21.4" +version = "0.22.0" include = [ "Cargo.toml", @@ -42,7 +42,6 @@ include = [ "src/signed_data.rs", "src/time.rs", "src/trust_anchor.rs", - "src/trust_anchor_util.rs", "src/verify_cert.rs", "src/lib.rs", @@ -68,19 +67,15 @@ all-features = true name = "webpki" [features] -# TODO: In the next release, make this non-default. -default = ["std"] alloc = ["ring/alloc"] std = ["alloc"] -# TODO: In the next release, remove this. -trust_anchor_util = ["std"] [dependencies] ring = { version = "0.16.19", default-features = false } untrusted = "0.7.1" [dev-dependencies] -base64 = "0.13" +base64 = "0.9.1" [profile.bench] opt-level = 3 diff --git a/mk/clippy.sh b/mk/clippy.sh index 2047ea15..e5173de4 100755 --- a/mk/clippy.sh +++ b/mk/clippy.sh @@ -22,16 +22,20 @@ cargo clippy \ --target-dir=target/clippy \ --all-features --all-targets \ -- \ - --deny missing_docs \ --deny warnings \ \ --deny clippy::as_conversions \ \ + --allow clippy::clone_on_copy \ --allow clippy::explicit_auto_deref \ --allow clippy::len_without_is_empty \ + --allow clippy::needless_borrow \ --allow clippy::new_without_default \ + --allow clippy::octal_escapes \ + --allow clippy::redundant_closure \ --allow clippy::single_match \ --allow clippy::single_match_else \ --allow clippy::type_complexity \ --allow clippy::upper_case_acronyms \ + --allow clippy::useless_asref \ $NULL diff --git a/src/calendar.rs b/src/calendar.rs index 0abe938b..f1d2c444 100644 --- a/src/calendar.rs +++ b/src/calendar.rs @@ -67,7 +67,7 @@ fn days_before_year_since_unix_epoch(year: u64) -> Result { // Unix epoch. It is likely that other software won't deal well with // certificates that have dates before the epoch. if year < 1970 { - return Err(Error::BadDERTime); + return Err(Error::BadDerTime); } let days_before_year_ad = days_before_year_ad(year); debug_assert!(days_before_year_ad >= DAYS_BEFORE_UNIX_EPOCH_AD); diff --git a/src/cert.rs b/src/cert.rs index 75e022a1..7c76f2e1 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -49,16 +49,16 @@ pub(crate) fn parse_cert_internal<'a>( ee_or_ca: EndEntityOrCa<'a>, serial_number: fn(input: &mut untrusted::Reader<'_>) -> Result<(), Error>, ) -> Result, Error> { - let (tbs, signed_data) = cert_der.read_all(Error::BadDER, |cert_der| { + let (tbs, signed_data) = cert_der.read_all(Error::BadDer, |cert_der| { der::nested( cert_der, der::Tag::Sequence, - Error::BadDER, + Error::BadDer, signed_data::parse_signed_data, ) })?; - tbs.read_all(Error::BadDER, |tbs| { + tbs.read_all(Error::BadDer, |tbs| { version3(tbs)?; serial_number(tbs)?; @@ -110,7 +110,7 @@ pub(crate) fn parse_cert_internal<'a>( tagged, der::Tag::Sequence, der::Tag::Sequence, - Error::BadDER, + Error::BadDer, |extension| { let extn_id = der::expect_tag_and_get_value(extension, der::Tag::OID)?; let critical = der::optional_boolean(extension)?; @@ -154,7 +154,7 @@ pub fn certificate_serial_number(input: &mut untrusted::Reader) -> Result<(), Er let value = der::positive_integer(input)?; if value.big_endian_without_leading_zero().len() > 20 { - return Err(Error::BadDER); + return Err(Error::BadDer); } Ok(()) } @@ -215,7 +215,7 @@ fn remember_extension<'a>( } None => { // All the extensions that we care about are wrapped in a SEQUENCE. - let sequence_value = value.read_all(Error::BadDER, |value| { + let sequence_value = value.read_all(Error::BadDer, |value| { der::expect_tag_and_get_value(value, der::Tag::Sequence) })?; *out = Some(sequence_value); diff --git a/src/der.rs b/src/der.rs index c4cad81b..43d0847d 100644 --- a/src/der.rs +++ b/src/der.rs @@ -23,7 +23,7 @@ pub fn expect_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result, Error> { - ring::io::der::expect_tag_and_get_value(input, tag).map_err(|_| Error::BadDER) + ring::io::der::expect_tag_and_get_value(input, tag).map_err(|_| Error::BadDer) } pub struct Value<'a> { @@ -39,7 +39,7 @@ impl<'a> Value<'a> { pub fn expect_tag<'a>(input: &mut untrusted::Reader<'a>, tag: Tag) -> Result, Error> { let (actual_tag, value) = read_tag_and_get_value(input)?; if usize::from(tag) != usize::from(actual_tag) { - return Err(Error::BadDER); + return Err(Error::BadDer); } Ok(Value { value }) @@ -49,7 +49,7 @@ pub fn expect_tag<'a>(input: &mut untrusted::Reader<'a>, tag: Tag) -> Result( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), Error> { - ring::io::der::read_tag_and_get_value(input).map_err(|_| Error::BadDER) + ring::io::der::read_tag_and_get_value(input).map_err(|_| Error::BadDer) } // TODO: investigate taking decoder as a reference to reduce generated code @@ -78,10 +78,10 @@ where pub fn bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result, Error> { - nested(input, Tag::BitString, Error::BadDER, |value| { - let unused_bits_at_end = value.read_byte().map_err(|_| Error::BadDER)?; + nested(input, Tag::BitString, Error::BadDer, |value| { + let unused_bits_at_end = value.read_byte().map_err(|_| Error::BadDer)?; if unused_bits_at_end != 0 { - return Err(Error::BadDER); + return Err(Error::BadDer); } Ok(value.read_bytes_to_end()) }) @@ -93,21 +93,21 @@ pub fn optional_boolean(input: &mut untrusted::Reader) -> Result { if !input.peek(Tag::Boolean.into()) { return Ok(false); } - nested(input, Tag::Boolean, Error::BadDER, |input| { + nested(input, Tag::Boolean, Error::BadDer, |input| { match input.read_byte() { Ok(0xff) => Ok(true), Ok(0x00) => Ok(false), - _ => Err(Error::BadDER), + _ => Err(Error::BadDer), } }) } pub fn positive_integer<'a>(input: &'a mut untrusted::Reader) -> Result, Error> { - ring::io::der::positive_integer(input).map_err(|_| Error::BadDER) + ring::io::der::positive_integer(input).map_err(|_| Error::BadDer) } pub fn small_nonnegative_integer(input: &mut untrusted::Reader) -> Result { - ring::io::der::small_nonnegative_integer(input).map_err(|_| Error::BadDER) + ring::io::der::small_nonnegative_integer(input).map_err(|_| Error::BadDer) } pub fn time_choice(input: &mut untrusted::Reader) -> Result { @@ -120,11 +120,11 @@ pub fn time_choice(input: &mut untrusted::Reader) -> Result { fn read_digit(inner: &mut untrusted::Reader) -> Result { const DIGIT: core::ops::RangeInclusive = b'0'..=b'9'; - let b = inner.read_byte().map_err(|_| Error::BadDERTime)?; + let b = inner.read_byte().map_err(|_| Error::BadDerTime)?; if DIGIT.contains(&b) { return Ok(u64::from(b - DIGIT.start())); } - Err(Error::BadDERTime) + Err(Error::BadDerTime) } fn read_two_digits(inner: &mut untrusted::Reader, min: u64, max: u64) -> Result { @@ -132,12 +132,12 @@ pub fn time_choice(input: &mut untrusted::Reader) -> Result { let lo = read_digit(inner)?; let value = (hi * 10) + lo; if value < min || value > max { - return Err(Error::BadDERTime); + return Err(Error::BadDerTime); } Ok(value) } - nested(input, expected_tag, Error::BadDER, |value| { + nested(input, expected_tag, Error::BadDer, |value| { let (year_hi, year_lo) = if is_utc_time { let lo = read_two_digits(value, 0, 99)?; let hi = if lo >= 50 { 19 } else { 20 }; @@ -156,9 +156,9 @@ pub fn time_choice(input: &mut untrusted::Reader) -> Result { let minutes = read_two_digits(value, 0, 59)?; let seconds = read_two_digits(value, 0, 59)?; - let time_zone = value.read_byte().map_err(|_| Error::BadDERTime)?; + let time_zone = value.read_byte().map_err(|_| Error::BadDerTime)?; if time_zone != b'Z' { - return Err(Error::BadDERTime); + return Err(Error::BadDerTime); } calendar::time_from_ymdhms_utc(year, month, day_of_month, hours, minutes, seconds) diff --git a/src/end_entity.rs b/src/end_entity.rs index 1161c305..8c0650a9 100644 --- a/src/end_entity.rs +++ b/src/end_entity.rs @@ -13,10 +13,12 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::{ - cert, name, signed_data, verify_cert, DnsNameRef, Error, SignatureAlgorithm, - TLSClientTrustAnchors, TLSServerTrustAnchors, Time, + cert, name, signed_data, verify_cert, DnsNameRef, Error, SignatureAlgorithm, Time, + TlsClientTrustAnchors, TlsServerTrustAnchors, }; -use core::convert::TryFrom; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; /// An end-entity certificate. /// @@ -57,7 +59,7 @@ pub struct EndEntityCert<'a> { inner: cert::Cert<'a>, } -impl<'a> TryFrom<&'a [u8]> for EndEntityCert<'a> { +impl<'a> core::convert::TryFrom<&'a [u8]> for EndEntityCert<'a> { type Error = Error; /// Parse the ASN.1 DER-encoded X.509 encoding of the certificate @@ -73,12 +75,6 @@ impl<'a> TryFrom<&'a [u8]> for EndEntityCert<'a> { } impl<'a> EndEntityCert<'a> { - /// Deprecated. Use `TryFrom::try_from`. - #[deprecated(note = "Use TryFrom::try_from")] - pub fn from(cert_der: &'a [u8]) -> Result { - TryFrom::try_from(cert_der) - } - pub(super) fn inner(&self) -> &cert::Cert { &self.inner } @@ -96,7 +92,7 @@ impl<'a> EndEntityCert<'a> { pub fn verify_is_valid_tls_server_cert( &self, supported_sig_algs: &[&SignatureAlgorithm], - &TLSServerTrustAnchors(trust_anchors): &TLSServerTrustAnchors, + &TlsServerTrustAnchors(trust_anchors): &TlsServerTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), Error> { @@ -128,7 +124,7 @@ impl<'a> EndEntityCert<'a> { pub fn verify_is_valid_tls_client_cert( &self, supported_sig_algs: &[&SignatureAlgorithm], - &TLSClientTrustAnchors(trust_anchors): &TLSClientTrustAnchors, + &TlsClientTrustAnchors(trust_anchors): &TlsClientTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), Error> { @@ -145,7 +141,33 @@ impl<'a> EndEntityCert<'a> { /// Verifies that the certificate is valid for the given DNS host name. pub fn verify_is_valid_for_dns_name(&self, dns_name: DnsNameRef) -> Result<(), Error> { - name::verify_cert_dns_name(self, dns_name) + name::verify_cert_dns_name(&self, dns_name) + } + + /// Verifies that the certificate is valid for at least one of the given DNS + /// host names. + /// + /// If the certificate is not valid for any of the given names then this + /// fails with `Error::CertNotValidForName`. Otherwise the DNS names for + /// which the certificate is valid are returned. + /// + /// Requires the `alloc` default feature; i.e. this isn't available in + /// `#![no_std]` configurations. + #[cfg(feature = "alloc")] + pub fn verify_is_valid_for_at_least_one_dns_name<'names, Names>( + &self, + dns_names: Names, + ) -> Result>, Error> + where + Names: Iterator>, + { + let result: Vec> = dns_names + .filter(|n| self.verify_is_valid_for_dns_name(*n).is_ok()) + .collect(); + if result.is_empty() { + return Err(Error::CertNotValidForName); + } + Ok(result) } /// Verifies the signature `signature` of message `msg` using the @@ -160,7 +182,7 @@ impl<'a> EndEntityCert<'a> { /// `DigitallySigned.algorithm` of TLS type `SignatureAndHashAlgorithm`. In /// TLS 1.2 a single `SignatureAndHashAlgorithm` may map to multiple /// `SignatureAlgorithm`s. For example, a TLS 1.2 - /// `SignatureAndHashAlgorithm` of (ECDSA, SHA-256) may map to any or all + /// `ignatureAndHashAlgorithm` of (ECDSA, SHA-256) may map to any or all /// of {`ECDSA_P256_SHA256`, `ECDSA_P384_SHA256`}, depending on how the TLS /// implementation is configured. /// diff --git a/src/error.rs b/src/error.rs index ae11bbc9..deeb9a83 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,12 +18,10 @@ use core::fmt; #[derive(Clone, Copy, Debug, PartialEq)] pub enum Error { /// The encoding of some ASN.1 DER-encoded item is invalid. - // TODO: Rename to `BadDer` in the next release. - BadDER, + BadDer, /// The encoding of an ASN.1 DER-encoded time is invalid. - // TODO: Rename to `BadDerTime` in the next release. - BadDERTime, + BadDerTime, /// A CA certificate is being used as an end-entity certificate. CaUsedAsEndEntity, diff --git a/src/lib.rs b/src/lib.rs index a70afe25..ce9e71a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,17 @@ #![doc(html_root_url = "https://briansmith.org/rustdoc/")] #![cfg_attr(not(feature = "std"), no_std)] +#![allow( + clippy::doc_markdown, + clippy::if_not_else, + clippy::inline_always, + clippy::items_after_statements, + clippy::missing_errors_doc, + clippy::module_name_repetitions, + clippy::single_match, + clippy::single_match_else +)] +#![deny(clippy::as_conversions)] #[cfg(any(test, feature = "alloc"))] #[cfg_attr(test, macro_use)] @@ -42,7 +53,6 @@ mod name; mod signed_data; mod time; mod trust_anchor; -pub mod trust_anchor_util; mod verify_cert; @@ -55,7 +65,7 @@ pub use { ECDSA_P384_SHA384, ED25519, }, time::Time, - trust_anchor::{TLSClientTrustAnchors, TLSServerTrustAnchors, TrustAnchor}, + trust_anchor::{TlsClientTrustAnchors, TlsServerTrustAnchors, TrustAnchor}, }; #[cfg(feature = "alloc")] @@ -69,14 +79,18 @@ pub use { }; #[cfg(feature = "alloc")] -#[allow(missing_docs, unknown_lints, clippy::upper_case_acronyms)] +#[allow(unknown_lints, clippy::upper_case_acronyms)] #[deprecated(note = "Use DnsName")] pub type DNSName = DnsName; #[deprecated(note = "use DnsNameRef")] -#[allow(missing_docs, unknown_lints, clippy::upper_case_acronyms)] +#[allow(unknown_lints, clippy::upper_case_acronyms)] pub type DNSNameRef<'a> = DnsNameRef<'a>; -#[deprecated(note = "use InvalidDnsNameError")] -#[allow(missing_docs, unknown_lints, clippy::upper_case_acronyms)] -pub type InvalidDNSNameError = InvalidDnsNameError; +#[deprecated(note = "use TlsServerTrustAnchors")] +#[allow(unknown_lints, clippy::upper_case_acronyms)] +pub type TLSServerTrustAnchors<'a> = TlsServerTrustAnchors<'a>; + +#[deprecated(note = "use TlsClientTrustAnchors")] +#[allow(unknown_lints, clippy::upper_case_acronyms)] +pub type TLSClientTrustAnchors<'a> = TlsClientTrustAnchors<'a>; diff --git a/src/name/dns_name.rs b/src/name/dns_name.rs index e4f18f20..e40e703f 100644 --- a/src/name/dns_name.rs +++ b/src/name/dns_name.rs @@ -125,7 +125,7 @@ impl<'a> DnsNameRef<'a> { pub fn to_owned(&self) -> DnsName { // DnsNameRef is already guaranteed to be valid ASCII, which is a // subset of UTF-8. - let s: &str = (*self).into(); + let s: &str = self.clone().into(); DnsName(s.to_ascii_lowercase()) } } diff --git a/src/name/ip_address.rs b/src/name/ip_address.rs index 1eedf169..fac53625 100644 --- a/src/name/ip_address.rs +++ b/src/name/ip_address.rs @@ -28,10 +28,10 @@ pub(super) fn presented_id_matches_constraint( constraint: untrusted::Input, ) -> Result { if name.len() != 4 && name.len() != 16 { - return Err(Error::BadDER); + return Err(Error::BadDer); } if constraint.len() != 8 && constraint.len() != 32 { - return Err(Error::BadDER); + return Err(Error::BadDer); } // an IPv4 address never matches an IPv6 constraint, and vice versa. @@ -39,7 +39,7 @@ pub(super) fn presented_id_matches_constraint( return Ok(false); } - let (constraint_address, constraint_mask) = constraint.read_all(Error::BadDER, |value| { + let (constraint_address, constraint_mask) = constraint.read_all(Error::BadDer, |value| { let address = value.read_bytes(constraint.len() / 2).unwrap(); let mask = value.read_bytes(constraint.len() / 2).unwrap(); Ok((address, mask)) diff --git a/src/name/verify.rs b/src/name/verify.rs index 749a9ea6..6082c19e 100644 --- a/src/name/verify.rs +++ b/src/name/verify.rs @@ -26,7 +26,7 @@ pub fn verify_cert_dns_name( dns_name: DnsNameRef, ) -> Result<(), Error> { let cert = cert.inner(); - let dns_name = untrusted::Input::from(dns_name.as_ref()); + let dns_name = untrusted::Input::from(dns_name.as_ref().as_ref()); iterate_names( cert.subject, cert.subject_alt_name, @@ -40,7 +40,7 @@ pub fn verify_cert_dns_name( } Some(false) => (), None => { - return NameIteration::Stop(Err(Error::BadDER)); + return NameIteration::Stop(Err(Error::BadDer)); } } } @@ -70,7 +70,7 @@ pub fn check_name_constraints( if !inner.peek(subtrees_tag.into()) { return Ok(None); } - let subtrees = der::nested(inner, subtrees_tag, Error::BadDER, |tagged| { + let subtrees = der::nested(inner, subtrees_tag, Error::BadDer, |tagged| { der::expect_tag_and_get_value(tagged, der::Tag::Sequence) })?; Ok(Some(subtrees)) @@ -152,7 +152,7 @@ fn check_presented_id_conforms_to_constraints_in_subtree( input: &mut untrusted::Reader<'b>, ) -> Result, Error> { let general_subtree = der::expect_tag_and_get_value(input, der::Tag::Sequence)?; - general_subtree.read_all(Error::BadDER, general_name) + general_subtree.read_all(Error::BadDer, |subtree| general_name(subtree)) } let base = match general_subtree(&mut constraints) { @@ -164,7 +164,7 @@ fn check_presented_id_conforms_to_constraints_in_subtree( let matches = match (name, base) { (GeneralName::DnsName(name), GeneralName::DnsName(base)) => { - dns_name::presented_id_matches_constraint(name, base).ok_or(Error::BadDER) + dns_name::presented_id_matches_constraint(name, base).ok_or(Error::BadDer) } (GeneralName::DirectoryName(name), GeneralName::DirectoryName(base)) => Ok( @@ -322,7 +322,7 @@ fn general_name<'a>(input: &mut untrusted::Reader<'a>) -> Result | UNIFORM_RESOURCE_IDENTIFIER_TAG | REGISTERED_ID_TAG => GeneralName::Unsupported(tag & !(CONTEXT_SPECIFIC | CONSTRUCTED)), - _ => return Err(Error::BadDER), + _ => return Err(Error::BadDer), }; Ok(name) } diff --git a/src/signed_data.rs b/src/signed_data.rs index fce767b8..834f9076 100644 --- a/src/signed_data.rs +++ b/src/signed_data.rs @@ -175,7 +175,7 @@ struct SubjectPublicKeyInfo<'a> { // `PublicKeyAlgorithm` for the `SignatureAlgorithm` that is matched when // parsing the signature. fn parse_spki_value(input: untrusted::Input) -> Result { - input.read_all(Error::BadDER, |input| { + input.read_all(Error::BadDer, |input| { let algorithm_id_value = der::expect_tag_and_get_value(input, der::Tag::Sequence)?; let key_value = der::bit_string_with_no_unused_bits(input)?; Ok(SubjectPublicKeyInfo { @@ -402,7 +402,7 @@ mod tests { let tsd = parse_test_signed_data(file_contents); let spki_value = untrusted::Input::from(&tsd.spki); let spki_value = spki_value - .read_all(Error::BadDER, |input| { + .read_all(Error::BadDer, |input| { der::expect_tag_and_get_value(input, der::Tag::Sequence) }) .unwrap(); @@ -415,14 +415,14 @@ mod tests { let algorithm = untrusted::Input::from(&tsd.algorithm); let algorithm = algorithm - .read_all(Error::BadDER, |input| { + .read_all(Error::BadDer, |input| { der::expect_tag_and_get_value(input, der::Tag::Sequence) }) .unwrap(); let signature = untrusted::Input::from(&tsd.signature); let signature = signature - .read_all(Error::BadDER, |input| { + .read_all(Error::BadDer, |input| { der::bit_string_with_no_unused_bits(input) }) .unwrap(); @@ -461,7 +461,7 @@ mod tests { let signature = untrusted::Input::from(&tsd.signature); assert_eq!( Err(expected_error), - signature.read_all(Error::BadDER, |input| { + signature.read_all(Error::BadDer, |input| { der::bit_string_with_no_unused_bits(input) }) ); @@ -482,7 +482,7 @@ mod tests { let spki = untrusted::Input::from(&tsd.spki); assert_eq!( Err(expected_error), - spki.read_all(Error::BadDER, |input| { + spki.read_all(Error::BadDer, |input| { der::expect_tag_and_get_value(input, der::Tag::Sequence) }) ); @@ -518,7 +518,7 @@ mod tests { test_verify_signed_data_signature_outer!( test_ecdsa_prime256v1_sha512_unused_bits_signature, "ecdsa-prime256v1-sha512-unused-bits-signature.pem", - Error::BadDER + Error::BadDer ); // XXX: We should have a variant of this test with a SHA-256 digest that gives // `Error::UnsupportedSignatureAlgorithmForPublicKey`. @@ -571,12 +571,12 @@ mod tests { test_parse_spki_bad_outer!( test_rsa_pkcs1_sha1_bad_key_der_length, "rsa-pkcs1-sha1-bad-key-der-length.pem", - Error::BadDER + Error::BadDer ); test_parse_spki_bad_outer!( test_rsa_pkcs1_sha1_bad_key_der_null, "rsa-pkcs1-sha1-bad-key-der-null.pem", - Error::BadDER + Error::BadDer ); test_verify_signed_data!( test_rsa_pkcs1_sha1_key_params_absent, @@ -610,7 +610,7 @@ mod tests { test_parse_spki_bad_outer!( test_rsa_pkcs1_sha256_key_encoded_ber, "rsa-pkcs1-sha256-key-encoded-ber.pem", - Error::BadDER + Error::BadDer ); test_verify_signed_data!( test_rsa_pkcs1_sha256_spki_non_null_params, @@ -755,7 +755,7 @@ mod tests { if line == end_section { break; } - base64.push_str(line); + base64.push_str(&line); } base64::decode(&base64).unwrap() diff --git a/src/time.rs b/src/time.rs index 4fa0daaf..0457cae7 100644 --- a/src/time.rs +++ b/src/time.rs @@ -23,13 +23,6 @@ pub struct Time(u64); impl Time { - /// Deprecated. Use `TryFrom::try_from`. - #[cfg(feature = "std")] - // Soft deprecation. #[deprecated(note = "Use TryFrom::try_from")] - pub fn try_from(time: std::time::SystemTime) -> Result { - core::convert::TryFrom::try_from(time) - } - /// Create a `webpki::Time` from a unix timestamp. /// /// It is usually better to use the less error-prone @@ -44,8 +37,7 @@ impl Time { #[cfg(feature = "std")] impl core::convert::TryFrom for Time { - // TODO: In the next release, make this `std::time::SystemTimeError`. - type Error = ring::error::Unspecified; + type Error = std::time::SystemTimeError; /// Create a `webpki::Time` from a `std::time::SystemTime`. /// @@ -58,9 +50,9 @@ impl core::convert::TryFrom for Time { /// # extern crate webpki; /// # /// #![cfg(feature = "std")] - /// use std::{convert::TryFrom, time::SystemTime}; + /// use std::{convert::TryFrom, time::{SystemTime, SystemTimeError}}; /// - /// # fn foo() -> Result<(), ring::error::Unspecified> { + /// # fn foo() -> Result<(), SystemTimeError> { /// let time = webpki::Time::try_from(SystemTime::now())?; /// # Ok(()) /// # } @@ -69,6 +61,5 @@ impl core::convert::TryFrom for Time { value .duration_since(std::time::UNIX_EPOCH) .map(|d| Self::from_seconds_since_unix_epoch(d.as_secs())) - .map_err(|_| ring::error::Unspecified) } } diff --git a/src/trust_anchor.rs b/src/trust_anchor.rs index 1e926b55..0ac2806e 100644 --- a/src/trust_anchor.rs +++ b/src/trust_anchor.rs @@ -28,11 +28,11 @@ pub struct TrustAnchor<'a> { /// Trust anchors which may be used for authenticating servers. #[derive(Debug)] -pub struct TLSServerTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]); +pub struct TlsServerTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]); /// Trust anchors which may be used for authenticating clients. #[derive(Debug)] -pub struct TLSClientTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]); +pub struct TlsClientTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]); impl<'a> TrustAnchor<'a> { /// Interprets the given DER-encoded certificate as a `TrustAnchor`. The @@ -57,7 +57,7 @@ impl<'a> TrustAnchor<'a> { possibly_invalid_certificate_serial_number, ) { Ok(cert) => Ok(Self::from(cert)), - Err(Error::UnsupportedCertVersion) => parse_cert_v1(cert_der).or(Err(Error::BadDER)), + Err(Error::UnsupportedCertVersion) => parse_cert_v1(cert_der).or(Err(Error::BadDer)), Err(err) => Err(err), } } @@ -86,9 +86,9 @@ impl<'a> From> for TrustAnchor<'a> { /// Parses a v1 certificate directly into a TrustAnchor. fn parse_cert_v1(cert_der: untrusted::Input) -> Result { // X.509 Certificate: https://tools.ietf.org/html/rfc5280#section-4.1. - cert_der.read_all(Error::BadDER, |cert_der| { - der::nested(cert_der, der::Tag::Sequence, Error::BadDER, |cert_der| { - let anchor = der::nested(cert_der, der::Tag::Sequence, Error::BadDER, |tbs| { + cert_der.read_all(Error::BadDer, |cert_der| { + der::nested(cert_der, der::Tag::Sequence, Error::BadDer, |cert_der| { + let anchor = der::nested(cert_der, der::Tag::Sequence, Error::BadDer, |tbs| { // The version number field does not appear in v1 certificates. certificate_serial_number(tbs)?; diff --git a/src/trust_anchor_util.rs b/src/trust_anchor_util.rs deleted file mode 100644 index 9453947d..00000000 --- a/src/trust_anchor_util.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015-2021 Brian Smith. -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -//! Deprecated. Use `TrustAnchor`. - -use crate::{Error, TrustAnchor}; - -/// Deprecated. Use TrustAnchor::try_from_cert_der. -#[deprecated(note = "Use TrustAnchor::try_from_cert_der")] -pub fn cert_der_as_trust_anchor(cert_der: &[u8]) -> Result { - TrustAnchor::try_from_cert_der(cert_der) -} diff --git a/src/verify_cert.rs b/src/verify_cert.rs index 8a6bed91..c68e6cf2 100644 --- a/src/verify_cert.rs +++ b/src/verify_cert.rs @@ -61,8 +61,8 @@ pub fn build_chain( let name_constraints = trust_anchor.name_constraints.map(untrusted::Input::from); - untrusted::read_all_optional(name_constraints, Error::BadDER, |value| { - name::check_name_constraints(value, cert) + untrusted::read_all_optional(name_constraints, Error::BadDer, |value| { + name::check_name_constraints(value, &cert) })?; let trust_anchor_spki = untrusted::Input::from(trust_anchor.spki); @@ -83,7 +83,7 @@ pub fn build_chain( loop_while_non_fatal_error(intermediate_certs, |cert_der| { let potential_issuer = - cert::parse_cert(untrusted::Input::from(*cert_der), EndEntityOrCa::Ca(cert))?; + cert::parse_cert(untrusted::Input::from(*cert_der), EndEntityOrCa::Ca(&cert))?; if potential_issuer.subject != cert.issuer { return Err(Error::UnknownIssuer); @@ -107,8 +107,8 @@ pub fn build_chain( } } - untrusted::read_all_optional(potential_issuer.name_constraints, Error::BadDER, |value| { - name::check_name_constraints(value, cert) + untrusted::read_all_optional(potential_issuer.name_constraints, Error::BadDer, |value| { + name::check_name_constraints(value, &cert) })?; let next_sub_ca_count = match used_as_ca { @@ -170,11 +170,11 @@ fn check_issuer_independent_properties( // KeyUsage extension. cert.validity - .read_all(Error::BadDER, |value| check_validity(value, time))?; - untrusted::read_all_optional(cert.basic_constraints, Error::BadDER, |value| { + .read_all(Error::BadDer, |value| check_validity(value, time))?; + untrusted::read_all_optional(cert.basic_constraints, Error::BadDer, |value| { check_basic_constraints(value, used_as_ca, sub_ca_count) })?; - untrusted::read_all_optional(cert.eku, Error::BadDER, |value| { + untrusted::read_all_optional(cert.eku, Error::BadDer, |value| { check_eku(value, required_eku_if_present) })?; diff --git a/tests/dns_name_tests.rs b/tests/dns_name_tests.rs index 0e519999..b3a3adc4 100644 --- a/tests/dns_name_tests.rs +++ b/tests/dns_name_tests.rs @@ -250,7 +250,7 @@ static IP_ADDRESS_DNS_VALIDITY: &[(&[u8], bool)] = &[ (b"1.2.3.4\n", false), // Nulls not allowed (b"\0", false), - (b"\x001.2.3.4", false), + (b"\01.2.3.4", false), (b"1.2.3.4\0", false), (b"1.2.3.4\0.5", false), // Range @@ -389,7 +389,7 @@ static IP_ADDRESS_DNS_VALIDITY: &[(&[u8], bool)] = &[ (b"::1\0:2", false), (b"::1\0", false), (b"::1.2.3.4\0", false), - (b"::1.2\x002.3.4", false), + (b"::1.2\02.3.4", false), ]; #[test] diff --git a/tests/integration.rs b/tests/integration.rs index 34270272..598641d3 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -41,7 +41,7 @@ pub fn netflix() { let ca = include_bytes!("netflix/ca.der"); let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()]; - let anchors = webpki::TLSServerTrustAnchors(&anchors); + let anchors = webpki::TlsServerTrustAnchors(&anchors); #[allow(clippy::unreadable_literal)] // TODO: Make this clear. let time = webpki::Time::from_seconds_since_unix_epoch(1492441716); @@ -59,7 +59,7 @@ pub fn ed25519() { let ca = include_bytes!("ed25519/ca.der"); let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()]; - let anchors = webpki::TLSServerTrustAnchors(&anchors); + let anchors = webpki::TlsServerTrustAnchors(&anchors); #[allow(clippy::unreadable_literal)] // TODO: Make this clear. let time = webpki::Time::from_seconds_since_unix_epoch(1547363522);