From 6c4c65f335a68a3d3a9bc3b03779409a3fd33746 Mon Sep 17 00:00:00 2001 From: Leopold Joy Date: Fri, 24 Jul 2026 21:32:50 +0100 Subject: [PATCH] fix: reject invalid certificate dates Co-authored-by: OpenCode --- src/Asn1Decode.sol | 5 +++++ test/Asn1Decode.t.sol | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/Asn1Decode.sol b/src/Asn1Decode.sol index 6e4f27f..2472b9d 100644 --- a/src/Asn1Decode.sol +++ b/src/Asn1Decode.sol @@ -307,6 +307,11 @@ library Asn1Decode { require(year >= 1970); require(1 <= month && month <= 12); require(1 <= day && day <= 31); + if (month == 2) { + require(day <= 28 || (day == 29 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)))); + } else if (month == 4 || month == 6 || month == 9 || month == 11) { + require(day <= 30); + } require(hour <= 23); require(minute <= 59); require(second <= 59); diff --git a/test/Asn1Decode.t.sol b/test/Asn1Decode.t.sol index d5577db..d7cf574 100644 --- a/test/Asn1Decode.t.sol +++ b/test/Asn1Decode.t.sol @@ -152,6 +152,26 @@ contract Asn1DecodeTest is Test { assertEq(h.timestampAtRoot(_generalizedTime("20240101000000Z")), 1704067200); } + function test_timestamp_february30_reverts() public { + vm.expectRevert(); + h.timestampAtRoot(_generalizedTime("20240230000000Z")); + } + + function test_timestamp_april31_reverts() public { + vm.expectRevert(); + h.timestampAtRoot(_generalizedTime("20240431000000Z")); + } + + function test_timestamp_nonLeapYearFebruary29_reverts() public { + vm.expectRevert(); + h.timestampAtRoot(_generalizedTime("20230229000000Z")); + } + + function test_timestamp_leapYearFebruary29() public view { + // GeneralizedTime "20240229000000Z" -> 2024-02-29T00:00:00Z + assertEq(h.timestampAtRoot(_generalizedTime("20240229000000Z")), 1709164800); + } + function test_timestamp_wrongType_reverts() public { bytes memory der = abi.encodePacked(hex"160d", bytes("700101000000Z")); // type 0x16 vm.expectRevert(Asn1Decode.InvalidAsn1Value.selector);