Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make x509::Time more useful #331

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.cargo
target/
venv/
venv/
.vscode
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ crypto (or PKI) only library.
* **time** Enable time support in mbedtls-sys.
* *zlib* Enable zlib support in mbedtls-sys.
* *async-rt* Enable async support for SSL.

PRs adding new features are encouraged.
* *chrono* Enable [`chrono`](https://docs.rs/chrono/) support (e.g., implementation of conversion traits between `x509::Time` and `chrono` types)

# mbedtls-sys-auto

Expand Down
1 change: 1 addition & 0 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ case "$TRAVIS_RUST_VERSION" in
if [ "$TARGET" != "x86_64-fortanix-unknown-sgx" ]; then
cargo nextest run --test async_session --features=async-rt,ssl --target $TARGET
cargo nextest run --test async_session --features=async-rt,ssl,legacy_protocols --target $TARGET
cargo nextest run chrono --features=chrono,ssl,x509 --target $TARGET
Taowyoo marked this conversation as resolved.
Show resolved Hide resolved

# If zlib is installed, test the zlib feature
if [ -n "$ZLIB_INSTALLED" ]; then
Expand Down
1 change: 1 addition & 0 deletions mbedtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cbc = { version = "0.1.2", optional = true }
rc2 = { version = "0.8.1", optional = true }
cfg-if = "1.0.0"
tokio = { version = "1.16.1", optional = true }
chrono = { version = "0.4", optional = true }

[target.x86_64-fortanix-unknown-sgx.dependencies]
rs-libc = "0.2.0"
Expand Down
86 changes: 79 additions & 7 deletions mbedtls/src/x509/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,19 @@ impl Time {
pub fn new(year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> Option<Time> {
if year < 10000 && month >= 1 && month <= 12 && day >= 1 && day <= 31 && hour < 24 && minute < 60 && second < 60 {
Some(Time {
year: year,
month: month,
day: day,
hour: hour,
minute: minute,
second: second,
year,
month,
day,
hour,
minute,
second,
})
} else {
None
}
}

fn to_x509_time(&self) -> [u8; 15] {
pub fn to_x509_time(&self) -> [u8; 15] {
let mut writer = TimeWriter { buf: [0; 15], idx: 0 };
write!(
writer,
Expand All @@ -219,4 +219,76 @@ impl Time {
assert!(writer.idx == 14);
writer.buf
}

pub fn year(&self) -> u16 {
self.year
}
pub fn month(&self) -> u8 {
self.month
}
pub fn day(&self) -> u8 {
self.day
}
pub fn hour(&self) -> u8 {
self.hour
}
pub fn minute(&self) -> u8 {
self.minute
}
pub fn second(&self) -> u8 {
self.second
}
}

#[cfg(feature = "chrono")]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub struct InvalidTimeError;

#[cfg(feature = "chrono")]
mod chrono_time {
use chrono::{Datelike, NaiveDate, NaiveDateTime, Timelike};
use core::convert::{TryFrom, TryInto};

use super::{InvalidTimeError, Time};

impl TryFrom<Time> for NaiveDateTime {
type Error = InvalidTimeError;

fn try_from(value: Time) -> Result<Self, Self::Error> {
let res = NaiveDate::from_ymd_opt(value.year.into(), value.month.into(), value.day.into())
.and_then(|date| date.and_hms_opt(value.hour.into(), value.minute.into(), value.second.into()))
.ok_or(InvalidTimeError)?;
Ok(res)
}
}

impl TryFrom<NaiveDateTime> for Time {
type Error = InvalidTimeError;

fn try_from(value: NaiveDateTime) -> Result<Self, Self::Error> {
let res = Time::new(
value.year().try_into().map_err(|_| InvalidTimeError)?,
value.month().try_into().map_err(|_| InvalidTimeError)?,
value.day().try_into().map_err(|_| InvalidTimeError)?,
value.hour().try_into().map_err(|_| InvalidTimeError)?,
value.minute().try_into().map_err(|_| InvalidTimeError)?,
value.second().try_into().map_err(|_| InvalidTimeError)?,
);
res.ok_or(InvalidTimeError)
}
}

#[test]
fn time_naive_date_time_conversion() {
let time = Time::new(2077, 12, 13, 10, 20, 30).unwrap();
let naive_date_time: NaiveDateTime = time.try_into().unwrap();

let expected = NaiveDate::from_ymd_opt(2077, 12, 13)
.unwrap()
.and_hms_opt(10, 20, 30)
.unwrap();
assert_eq!(naive_date_time, expected);

assert_eq!(time, Time::try_from(naive_date_time).unwrap());
}
}