Skip to content

Commit 69b7699

Browse files
BiagioFestaancwrd1
authored andcommitted
CertContext: method to retrieve time when added to store
1 parent 351916a commit 69b7699

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ no-default-features = true
1616

1717
[dependencies]
1818
rustls = { version = "0.23", default-features = false, features = ["std"] }
19+
time = { version = "0.3.43", default-features = false, optional = true }
1920
windows-sys = { version = "0.60", features = ["Win32_Foundation", "Win32_Security_Cryptography"] }
2021

2122
[dev-dependencies]
@@ -29,4 +30,5 @@ aws-lc-rs = ["rustls/aws_lc_rs"]
2930
fips = ["rustls/fips"]
3031
logging = ["rustls/logging"]
3132
ring = ["rustls/ring"]
33+
time = ["dep:time"]
3234
tls12 = ["rustls/tls12"]

src/cert.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,50 @@ impl CertContext {
161161
}
162162
}
163163
}
164+
165+
/// Returns the time when the certificate was added to the store.
166+
///
167+
/// `None` if the property is not set.
168+
#[cfg(feature = "time")]
169+
pub fn timestamp(&self) -> Result<Option<time::UtcDateTime>> {
170+
use std::time::Duration;
171+
use windows_sys::core::HRESULT;
172+
use windows_sys::Win32::Foundation::{GetLastError, CRYPT_E_NOT_FOUND, FILETIME};
173+
174+
// Duration between Windows epoch (1601-01-01) and Unix epoch (1970-01-01)
175+
const WINDOWS_TO_UNIX_EPOCH: Duration = Duration::from_secs(11_644_473_600);
176+
177+
let mut filetime = FILETIME::default();
178+
let mut size = mem::size_of::<FILETIME>() as u32;
179+
180+
let success = unsafe {
181+
CertGetCertificateContextProperty(
182+
self.inner(),
183+
CERT_DATE_STAMP_PROP_ID,
184+
&mut filetime as *mut _ as *mut _,
185+
&mut size,
186+
)
187+
} != 0;
188+
189+
if !success {
190+
let error = unsafe { GetLastError() };
191+
return match error as HRESULT {
192+
CRYPT_E_NOT_FOUND => Ok(None),
193+
_ => Err(CngError::WindowsError(error)),
194+
};
195+
}
196+
197+
let ticks = ((filetime.dwHighDateTime as u64) << 32) | filetime.dwLowDateTime as u64;
198+
199+
// Each tick is 100 nanoseconds (FILETIME is in 100ns units)
200+
let duration_since_windows_epoch = Duration::from_nanos(ticks * 100);
201+
202+
let duration_since_unix_epoch = duration_since_windows_epoch
203+
.checked_sub(WINDOWS_TO_UNIX_EPOCH)
204+
.unwrap_or(Duration::ZERO);
205+
206+
let timestamp = time::UtcDateTime::UNIX_EPOCH + duration_since_unix_epoch;
207+
208+
Ok(Some(timestamp))
209+
}
164210
}

0 commit comments

Comments
 (0)