@@ -310,43 +310,78 @@ def test_new_timestamp_unsigned(self) -> None:
310310
311311 @patch .object (datetime , "datetime" , wraps = datetime .datetime )
312312 def test_expired_timestamp_version_rollback (self , mock_time : Mock ) -> None :
313+ """Verifies that local timestamp is used in rollback checks even if it is expired.
314+
315+ The timestamp updates and rollback checks are performed
316+ with the following timing:
317+ - Timestamp v1 expiry set to day 7
318+ - First updater refresh performed on day 0
319+ - Repository publishes timestamp v2 on day 0
320+ - Timestamp v2 expiry set to day 21
321+ - Second updater refresh performed on day 18:
322+ assert that rollback check uses expired timestamp v1"""
323+
324+ now = datetime .datetime .utcnow ()
325+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
326+
327+ self .sim .timestamp .version = 2
328+
329+ # Make a successful update of valid metadata which stores it in cache
313330 self ._run_refresh ()
314331
332+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
333+
334+ self .sim .timestamp .version = 1
335+
315336 mock_time .utcnow .return_value = (
316- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
337+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
317338 )
318339 with patch ("datetime.datetime" , mock_time ):
319- # Check for a rollback attack
320- self .sim .timestamp .version = 2
321- self ._run_refresh ()
322-
323- self .sim .timestamp .version = 1
340+ # Check that a rollback protection is performed even if
341+ # local timestamp has expired
324342 with self .assertRaises (BadVersionNumberError ):
325343 self ._run_refresh ()
326344
327- self ._assert_version_equals (Timestamp .type , 2 )
345+ self ._assert_version_equals (Timestamp .type , 2 )
328346
329347 @patch .object (datetime , "datetime" , wraps = datetime .datetime )
330348 def test_expired_timestamp_snapshot_rollback (self , mock_time : Mock ) -> None :
349+ """Verifies that rollback protection is done even if local timestamp has expired.
350+
351+ The snapshot updates and rollback protection checks are performed
352+ with the following timing:
353+ - Timestamp v1 expiry set to day 7
354+ - Repository bumps snapshot to v3 on day 0
355+ - First updater refresh performed on day 0
356+ - Timestamp v2 expiry set to day 21
357+ - Second updater refresh performed on day 18:
358+ assert that rollback protection is done with expired timestamp v1"""
359+
360+ now = datetime .datetime .utcnow ()
361+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
362+
363+ # Bump the snapshot version number to 3
364+ self .sim .update_snapshot ()
365+ self .sim .update_snapshot ()
366+
367+ # Make a successful update of valid metadata which stores it in cache
331368 self ._run_refresh ()
332369
370+ self .sim .snapshot .version = 1
371+ # Snapshot version number is set to 2, which is still less than 3
372+ self .sim .update_snapshot ()
373+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
374+
333375 mock_time .utcnow .return_value = (
334- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
376+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
335377 )
336378 with patch ("datetime.datetime" , mock_time ):
337- # Check for a rollback attack.
338- self .sim .snapshot .version = 2
339- self .sim .update_timestamp () # timestamp v2
340- self ._run_refresh ()
341-
342- # Snapshot meta version is smaller than previous
343- self .sim .timestamp .snapshot_meta .version = 1
344- self .sim .timestamp .version += 1 # timestamp v3
345-
379+ # Assert that rollback protection is done even if
380+ # local timestamp has expired
346381 with self .assertRaises (BadVersionNumberError ):
347382 self ._run_refresh ()
348383
349- self ._assert_version_equals (Timestamp .type , 2 )
384+ self ._assert_version_equals (Timestamp .type , 3 )
350385
351386 def test_new_timestamp_version_rollback (self ) -> None :
352387 # Check for a rollback attack
@@ -706,22 +741,34 @@ def test_load_metadata_from_cache(self, wrapped_open: MagicMock) -> None:
706741
707742 @patch .object (datetime , "datetime" , wraps = datetime .datetime )
708743 def test_expired_metadata (self , mock_time : Mock ) -> None :
709- # Test that expired local timestamp/snapshot can be used for updating
710- # from remote
744+ """Verifies that expired local timestamp/snapshot can be used for
745+ updating from remote.
746+
747+ The updates and verifications are performed with the following timing:
748+ - Timestamp v1 expiry set to day 7
749+ - First updater refresh performed on day 0
750+ - Repository bumps snapshot and targets to v2 on day 0
751+ - Timestamp v2 expiry set to day 21
752+ - Second updater refresh performed on day 18,
753+ it is successful and timestamp/snaphot final versions are v2"""
754+
755+ now = datetime .datetime .utcnow ()
756+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
711757
712758 # Make a successful update of valid metadata which stores it in cache
713759 self ._run_refresh ()
714760
715- # Simulate expired local metadata by mocking system time one second ahead
761+ self .sim .targets .version += 1
762+ self .sim .update_snapshot ()
763+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
764+
765+ # Mocking time so that local timestam has expired
766+ # but the new timestamp has not
716767 mock_time .utcnow .return_value = (
717- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
768+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
718769 )
719770 with patch ("datetime.datetime" , mock_time ):
720- self .sim .targets .version += 1
721- self .sim .update_snapshot ()
722- # Create a new updater and perform a second update while
723- # the metadata is already stored in cache (metadata dir)
724- self ._run_refresh ()
771+ self ._run_refresh ()
725772
726773 # Assert that the final version of timestamp/snapshot is version 2
727774 # which means a successful refresh is performed
0 commit comments