Skip to content

Commit 38df3e6

Browse files
gilcu3netrome
andauthored
fix: Extend max collateral age (#3941) (#3945)
Co-authored-by: Mårten Blankfors <marten@blankfors.se>
1 parent 20bb289 commit 38df3e6

1 file changed

Lines changed: 19 additions & 16 deletions

File tree

crates/tee-authority/src/tee_authority.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -224,22 +224,25 @@ const MAX_BACKOFF_DURATION: Duration = Duration::from_secs(60);
224224
/// to splitting them, and the redundancy is harmless.
225225
const PCCS_REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
226226

227-
/// Maximum age accepted for PCCS collateral. Hard-coded at 7 days.
227+
/// Maximum age accepted for PCCS collateral. Hard-coded at 31 days.
228228
/// Lives in the node binary (governed via image-hash approval), not
229229
/// as per-operator configuration.
230230
///
231-
/// 7 days is stricter than Intel's 30-day `nextUpdate` window but
232-
/// more permissive than any default PCCS refresh schedule (Intel
233-
/// reference and Phala both refresh ~daily), so legitimate operators
234-
/// have ample headroom. This is the freshness bound on the collateral's
235-
/// Intel signature and is independent of the contract's attestation
236-
/// expiry (`DEFAULT_EXPIRATION_DURATION_SECONDS`); the two windows serve
231+
/// Intel sets each collateral's `nextUpdate` 30 days after issuance and
232+
/// expects a refresh at least that often (see
233+
/// <https://cc-enabling.trustedservices.intel.com/intel-tdx-enabling-guide/02/infrastructure_setup/>);
234+
/// 31 days accepts collateral for its full Intel-declared validity plus a
235+
/// day of headroom, so operators refreshing on Intel's own schedule are
236+
/// never rejected for age. This is the freshness bound on the
237+
/// collateral's Intel signature and is independent of the contract's
238+
/// attestation expiry
239+
/// (`DEFAULT_EXPIRATION_DURATION_SECONDS`); the two windows serve
237240
/// different purposes and are not required to match.
238241
///
239242
/// Applies uniformly to the three periodically re-signed pieces of
240243
/// collateral that share Intel's 30-day window: `tcb_info.issueDate`,
241244
/// `qe_identity.issueDate`, and PCK CRL `thisUpdate`.
242-
const MAX_COLLATERAL_AGE: time::Duration = time::Duration::days(7);
245+
const MAX_COLLATERAL_AGE: time::Duration = time::Duration::days(31);
243246

244247
/// Grace window for collateral whose Intel-issued timestamp (TCB Info /
245248
/// QE Identity `issueDate`, or PCK CRL `thisUpdate`) is slightly in our
@@ -1155,7 +1158,7 @@ mod tests {
11551158
/// clock. Constructed relative to the fixture PCK CRL's
11561159
/// `thisUpdate` so the fixture CRL is fresh for tests that exercise
11571160
/// only the JSON-field path; the offset is well under
1158-
/// [`MAX_COLLATERAL_AGE`] so a 7-day-back JSON `issueDate` still
1161+
/// [`MAX_COLLATERAL_AGE`] so a slightly-back JSON `issueDate` still
11591162
/// fits without underflowing into the future-grace path.
11601163
fn test_now() -> time::OffsetDateTime {
11611164
let crl_thisupdate =
@@ -1166,11 +1169,11 @@ mod tests {
11661169
/// Offset of [`test_now`] from the fixture CRL's `thisUpdate`. ~43
11671170
/// minutes — long enough that downstream `rfc3339(test_now() - X)`
11681171
/// round-trips don't lose sub-minute precision, short enough that
1169-
/// the CRL stays freshly within the 7-day window.
1172+
/// the CRL stays freshly within [`MAX_COLLATERAL_AGE`].
11701173
const TEST_NOW_OFFSET_FROM_FIXTURE_CRL: time::Duration = time::Duration::minutes(43);
11711174

1172-
/// Collateral whose `issueDate` is 6 days old (well within the 7-day
1173-
/// window) is accepted.
1175+
/// Collateral whose `issueDate` is 6 days old (well within
1176+
/// [`MAX_COLLATERAL_AGE`]) is accepted.
11741177
#[test]
11751178
fn check_collateral_freshness__should_accept_within_window() {
11761179
let issued = rfc3339(test_now() - time::Duration::days(6));
@@ -1185,7 +1188,7 @@ mod tests {
11851188
/// Typed `TooStale` variant identifies which field tripped the check.
11861189
#[test]
11871190
fn check_collateral_freshness__should_reject_when_tcb_info_too_old() {
1188-
let stale_tcb = rfc3339(test_now() - time::Duration::days(8));
1191+
let stale_tcb = rfc3339(test_now() - MAX_COLLATERAL_AGE - time::Duration::days(1));
11891192
let fresh_qe = rfc3339(test_now() - time::Duration::days(1));
11901193
let collateral = collateral_with_issue_dates(&stale_tcb, &fresh_qe);
11911194

@@ -1206,7 +1209,7 @@ mod tests {
12061209
#[test]
12071210
fn check_collateral_freshness__should_reject_when_qe_identity_too_old() {
12081211
let fresh_tcb = rfc3339(test_now() - time::Duration::days(1));
1209-
let stale_qe = rfc3339(test_now() - time::Duration::days(8));
1212+
let stale_qe = rfc3339(test_now() - MAX_COLLATERAL_AGE - time::Duration::days(1));
12101213
let collateral = collateral_with_issue_dates(&fresh_tcb, &stale_qe);
12111214

12121215
let err = check_collateral_freshness(&collateral, test_now()).unwrap_err();
@@ -1281,8 +1284,8 @@ mod tests {
12811284
#[test]
12821285
fn check_collateral_freshness__should_reject_when_pck_crl_too_old() {
12831286
// Fixture CRL's thisUpdate is 2026-03-30T11:17:23Z; pick a `now`
1284-
// ~9 days later so the CRL is past the 7-day window.
1285-
let now = test_now() + time::Duration::days(9);
1287+
// past MAX_COLLATERAL_AGE so the CRL is stale.
1288+
let now = test_now() + MAX_COLLATERAL_AGE + time::Duration::days(1);
12861289
// JSON fields fresh relative to `now` so only the CRL trips.
12871290
let fresh_iso = rfc3339(now - time::Duration::days(1));
12881291
let collateral = collateral_with_issue_dates(&fresh_iso, &fresh_iso);

0 commit comments

Comments
 (0)