From 12a86afcef726791fcf7348dc751a63f89850881 Mon Sep 17 00:00:00 2001 From: Matthew Mahnke Date: Thu, 27 Aug 2020 18:14:26 -0500 Subject: [PATCH 1/2] implement TryFrom for Time --- src/time.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/time.rs b/src/time.rs index 9d335837..03ac22db 100644 --- a/src/time.rs +++ b/src/time.rs @@ -23,10 +23,22 @@ pub struct Time(u64); impl Time { - /// Create a `webpki::Time` from a `std::time::SystemTime`. + /// Create a `webpki::Time` from a unix timestamp. /// - /// This will be replaced with a real `TryFrom` - /// implementation when `TryFrom` is added to Rust Stable. + /// It is usually better to use the less error-prone + /// `webpki::Time::try_from(time: std::time::SystemTime)` instead when + /// `std::time::SystemTime` is available (when `#![no_std]` isn't being + /// used). + pub fn from_seconds_since_unix_epoch(secs: u64) -> Time { + Time(secs) + } +} + +#[cfg(feature = "std")] +impl core::convert::TryFrom for Time { + type Error = ring::error::Unspecified; + + /// Create a `webpki::Time` from a `std::time::SystemTime`. /// /// # Example: /// @@ -36,28 +48,18 @@ impl Time { /// # extern crate ring; /// # extern crate webpki; /// # - /// #[cfg(feature = "std")] + /// #![cfg(feature = "std")] + /// use std::{convert::TryFrom, time::SystemTime}; + /// /// # fn foo() -> Result<(), ring::error::Unspecified> { - /// let time = webpki::Time::try_from(std::time::SystemTime::now())?; + /// let time = webpki::Time::try_from(SystemTime::now())?; /// # Ok(()) /// # } /// ``` - /// - /// Requires the `std` feature. - #[cfg(feature = "std")] - pub fn try_from(time: std::time::SystemTime) -> Result { - time.duration_since(std::time::UNIX_EPOCH) + fn try_from(value: std::time::SystemTime) -> Result { + value + .duration_since(std::time::UNIX_EPOCH) .map(|d| Time::from_seconds_since_unix_epoch(d.as_secs())) .map_err(|_| ring::error::Unspecified) } - - /// Create a `webpki::Time` from a unix timestamp. - /// - /// It is usually better to use the less error-prone - /// `webpki::Time::try_from(time: &std::time::SystemTime)` instead when - /// `std::time::SystemTime` is available (when `#![no_std]` isn't being - /// used). - pub fn from_seconds_since_unix_epoch(secs: u64) -> Time { - Time(secs) - } } From cea78b0829b3eda357def1567804ac464a7128e3 Mon Sep 17 00:00:00 2001 From: Matthew Mahnke Date: Thu, 27 Aug 2020 19:11:44 -0500 Subject: [PATCH 2/2] implement TryFrom for EndEntityCert --- src/webpki.rs | 8 ++++++-- tests/integration.rs | 9 +++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/webpki.rs b/src/webpki.rs index a5613152..feb6efd9 100644 --- a/src/webpki.rs +++ b/src/webpki.rs @@ -108,10 +108,12 @@ pub struct EndEntityCert<'a> { inner: cert::Cert<'a>, } -impl<'a> 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 /// `cert_der`. - pub fn from(cert_der: &'a [u8]) -> Result { + fn try_from(cert_der: &'a [u8]) -> Result { Ok(Self { inner: cert::parse_cert( untrusted::Input::from(cert_der), @@ -119,7 +121,9 @@ impl<'a> EndEntityCert<'a> { )?, }) } +} +impl<'a> EndEntityCert<'a> { /// Verifies that the end-entity certificate is valid for use by a TLS /// server. /// diff --git a/tests/integration.rs b/tests/integration.rs index 8e7abddc..0f39f3cc 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -12,6 +12,7 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +use core::convert::TryFrom; extern crate webpki; static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[ @@ -35,7 +36,7 @@ static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[ #[cfg(feature = "alloc")] #[test] pub fn netflix() { - let ee = include_bytes!("netflix/ee.der"); + let ee: &[u8] = include_bytes!("netflix/ee.der"); let inter = include_bytes!("netflix/inter.der"); let ca = include_bytes!("netflix/ca.der"); @@ -45,7 +46,7 @@ pub fn netflix() { #[allow(clippy::unreadable_literal)] // TODO: Make this clear. let time = webpki::Time::from_seconds_since_unix_epoch(1492441716); - let cert = webpki::EndEntityCert::from(ee).unwrap(); + let cert = webpki::EndEntityCert::try_from(ee).unwrap(); assert_eq!( Ok(()), cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[inter], time) @@ -54,7 +55,7 @@ pub fn netflix() { #[test] pub fn ed25519() { - let ee = include_bytes!("ed25519/ee.der"); + let ee: &[u8] = include_bytes!("ed25519/ee.der"); let ca = include_bytes!("ed25519/ca.der"); let anchors = vec![webpki::trust_anchor_util::cert_der_as_trust_anchor(ca).unwrap()]; @@ -63,7 +64,7 @@ pub fn ed25519() { #[allow(clippy::unreadable_literal)] // TODO: Make this clear. let time = webpki::Time::from_seconds_since_unix_epoch(1547363522); - let cert = webpki::EndEntityCert::from(ee).unwrap(); + let cert = webpki::EndEntityCert::try_from(ee).unwrap(); assert_eq!( Ok(()), cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[], time)