@@ -478,6 +478,19 @@ contract HintedNitroAttestationTest is Test {
478478 certManager.verifyCACertWithHints (abi.encodePacked (caCert, bytes1 (0x00 )), parentHash, "" );
479479 }
480480
481+ function test_HintedCACertRejectsNonCanonicalOuterLength () public {
482+ bytes memory attestation = _repairMissingPublicKeyBytes (_decodeBase64 (_realAttestationB64 ()));
483+ (bytes memory attestationTbs ,) = validator.decodeAttestationTbs (attestation);
484+ NitroValidator.Ptrs memory ptrs = parser.parseAttestation (attestationTbs);
485+ (bytes memory caCert , bytes32 parentHash ,) = _firstNonRootCA (attestationTbs, ptrs);
486+ bytes memory nonCanonicalCert = _nonCanonicalOuterSequenceLength (caCert);
487+ bytes32 nonCanonicalHash = keccak256 (nonCanonicalCert);
488+
489+ vm.expectRevert ("non-canonical ASN.1 length " );
490+ certManager.verifyCACertWithHints (nonCanonicalCert, parentHash, "" );
491+ assertEq (certManager.loadVerified (nonCanonicalHash).pubKey.length , 0 , "non-canonical cert must not cache " );
492+ }
493+
481494 function test_HintedTrailingRootBytesCannotPoisonParentCache () public {
482495 bytes memory attestation = _repairMissingPublicKeyBytes (_decodeBase64 (_realAttestationB64 ()));
483496 (bytes memory attestationTbs ,) = validator.decodeAttestationTbs (attestation);
@@ -1255,6 +1268,21 @@ contract HintedNitroAttestationTest is Test {
12551268 output[3 ] = bytes1 (uint8 (length));
12561269 }
12571270
1271+ function _nonCanonicalOuterSequenceLength (bytes memory der ) internal pure returns (bytes memory output ) {
1272+ require (der.length >= 4 && der[0 ] == 0x30 && der[1 ] == 0x82 , "test: expected long sequence " );
1273+
1274+ output = new bytes (der.length + 1 );
1275+ output[0 ] = der[0 ];
1276+ output[1 ] = 0x83 ;
1277+ output[2 ] = 0x00 ;
1278+ output[3 ] = der[2 ];
1279+ output[4 ] = der[3 ];
1280+
1281+ for (uint256 i = 4 ; i < der.length ; ++ i) {
1282+ output[i + 1 ] = der[i];
1283+ }
1284+ }
1285+
12581286 function _repairMissingPublicKeyBytes (bytes memory attestation ) internal pure returns (bytes memory repaired ) {
12591287 // The pasted Base64 sample is missing "ic_" in the CBOR key
12601288 // "public_key", but the key length and outer COSE payload length still
0 commit comments