1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // Copyright by contributors to this project. 3 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 4 5 use crate::{client::MlsError, time::MlsTime}; 6 use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize}; 7 8 #[derive(Clone, Debug, PartialEq, Eq, MlsSize, MlsEncode, MlsDecode, Default)] 9 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] 10 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 11 #[non_exhaustive] 12 pub struct Lifetime { 13 pub not_before: u64, 14 pub not_after: u64, 15 } 16 17 impl Lifetime { new(not_before: u64, not_after: u64) -> Lifetime18 pub fn new(not_before: u64, not_after: u64) -> Lifetime { 19 Lifetime { 20 not_before, 21 not_after, 22 } 23 } 24 seconds(s: u64) -> Result<Self, MlsError>25 pub fn seconds(s: u64) -> Result<Self, MlsError> { 26 #[cfg(feature = "std")] 27 let not_before = MlsTime::now().seconds_since_epoch(); 28 #[cfg(not(feature = "std"))] 29 // There is no clock on no_std, this is here just so that we can run tests. 30 let not_before = 3600u64; 31 32 let not_after = not_before.checked_add(s).ok_or(MlsError::TimeOverflow)?; 33 34 Ok(Lifetime { 35 // Subtract 1 hour to address time difference between machines 36 not_before: not_before - 3600, 37 not_after, 38 }) 39 } 40 days(d: u32) -> Result<Self, MlsError>41 pub fn days(d: u32) -> Result<Self, MlsError> { 42 Self::seconds((d * 86400) as u64) 43 } 44 years(y: u8) -> Result<Self, MlsError>45 pub fn years(y: u8) -> Result<Self, MlsError> { 46 Self::days(365 * y as u32) 47 } 48 within_lifetime(&self, time: MlsTime) -> bool49 pub(crate) fn within_lifetime(&self, time: MlsTime) -> bool { 50 let since_epoch = time.seconds_since_epoch(); 51 since_epoch >= self.not_before && since_epoch <= self.not_after 52 } 53 } 54 55 #[cfg(test)] 56 mod tests { 57 use core::time::Duration; 58 59 use super::*; 60 use assert_matches::assert_matches; 61 62 #[test] test_lifetime_overflow()63 fn test_lifetime_overflow() { 64 let res = Lifetime::seconds(u64::MAX); 65 assert_matches!(res, Err(MlsError::TimeOverflow)) 66 } 67 68 #[test] test_seconds()69 fn test_seconds() { 70 let seconds = 10; 71 let lifetime = Lifetime::seconds(seconds).unwrap(); 72 assert_eq!(lifetime.not_after - lifetime.not_before, 3610); 73 } 74 75 #[test] test_days()76 fn test_days() { 77 let days = 2; 78 let lifetime = Lifetime::days(days).unwrap(); 79 80 assert_eq!( 81 lifetime.not_after - lifetime.not_before, 82 86400u64 * days as u64 + 3600 83 ); 84 } 85 86 #[test] test_years()87 fn test_years() { 88 let years = 2; 89 let lifetime = Lifetime::years(years).unwrap(); 90 91 assert_eq!( 92 lifetime.not_after - lifetime.not_before, 93 86400 * 365 * years as u64 + 3600 94 ); 95 } 96 97 #[test] test_bounds()98 fn test_bounds() { 99 let test_lifetime = Lifetime { 100 not_before: 5, 101 not_after: 10, 102 }; 103 104 assert!(!test_lifetime 105 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(4)))); 106 107 assert!(!test_lifetime 108 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(11)))); 109 110 assert!(test_lifetime 111 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(5)))); 112 113 assert!(test_lifetime 114 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(10)))); 115 116 assert!(test_lifetime 117 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(6)))); 118 } 119 } 120