@@ -28,6 +28,10 @@ contract Asn1Harness {
2828 return der.bitstring (der.root ()).content ();
2929 }
3030
31+ function bitstringUintAtRoot (bytes memory der ) external pure returns (uint256 ) {
32+ return der.bitstringUintAt (der.root ());
33+ }
34+
3135 function firstChildHeader (bytes memory der ) external pure returns (uint256 ) {
3236 return der.firstChildOf (der.root ()).header ();
3337 }
@@ -131,6 +135,41 @@ contract Asn1DecodeTest is Test {
131135 h.bitstringContent (hex "03020100 " ); // pad byte is 0x01, not 0x00
132136 }
133137
138+ function test_bitstringUintAt_oneByteKeyUsage () public view {
139+ // X.509 KeyUsage bit 0 (digitalSignature): one content byte, 7 unused low bits.
140+ assertEq (h.bitstringUintAtRoot (hex "03020780 " ), 0x80 );
141+ }
142+
143+ function test_bitstringUintAt_twoByteKeyUsageNormalizesFirstOctet () public view {
144+ // X.509 KeyUsage bits 5 and 8 (keyCertSign | decipherOnly). The first content octet must
145+ // remain in the low byte so CertManager's 0x04 keyCertSign mask still targets bit 5.
146+ uint256 keyCertSignAndDecipherOnly = h.bitstringUintAtRoot (hex "0303070480 " );
147+ assertEq (keyCertSignAndDecipherOnly & 0x04 , 0x04 , "keyCertSign must stay in low byte " );
148+ assertEq (keyCertSignAndDecipherOnly & 0x80 , 0 , "decipherOnly must not alias digitalSignature " );
149+ assertEq (keyCertSignAndDecipherOnly, 0x8004 );
150+ }
151+
152+ function test_bitstringUintAt_twoByteDecipherOnlyDoesNotAliasDigitalSignature () public view {
153+ uint256 decipherOnly = h.bitstringUintAtRoot (hex "0303070080 " );
154+ assertEq (decipherOnly & 0x80 , 0 , "decipherOnly must not satisfy digitalSignature " );
155+ assertEq (decipherOnly, 0x8000 );
156+ }
157+
158+ function test_bitstringUintAt_nonZeroUnusedBits_reverts () public {
159+ vm.expectRevert ("Non-zero unused BIT STRING bits " );
160+ h.bitstringUintAtRoot (hex "03030700ff " );
161+ }
162+
163+ function test_bitstringUintAt_invalidUnusedBits_reverts () public {
164+ vm.expectRevert ("invalid BIT STRING padding " );
165+ h.bitstringUintAtRoot (hex "03020880 " );
166+ }
167+
168+ function test_bitstringUintAt_missingUnusedBits_reverts () public {
169+ vm.expectRevert ("invalid BIT STRING length " );
170+ h.bitstringUintAtRoot (hex "0300 " );
171+ }
172+
134173 // --- firstChildOf ---
135174
136175 function test_firstChildOf_notConstructed_reverts () public {
0 commit comments