Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/CertManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,15 @@ contract CertManager is ICertManager {
function _certSignature(bytes memory certificate, Asn1Ptr sigPtr) internal pure returns (bytes memory sigPacked) {
Asn1Ptr sigBPtr = certificate.bitstring(sigPtr);
Asn1Ptr sigRoot = certificate.rootOf(sigBPtr);
_requireAsn1Tag(certificate, sigRoot, 0x30);
Asn1Ptr sigRPtr = certificate.firstChildOf(sigRoot);
Asn1Ptr sigSPtr = certificate.nextSiblingOf(sigRPtr);
if (
sigRoot.header() + sigRoot.totalLength() != sigBPtr.content() + sigBPtr.length()
|| sigSPtr.header() + sigSPtr.totalLength() != sigRoot.content() + sigRoot.length()
) {
revert InvalidAsn1Tag();
}
(uint128 rhi, uint256 rlo) = certificate.uint384At(sigRPtr);
(uint128 shi, uint256 slo) = certificate.uint384At(sigSPtr);
sigPacked = abi.encodePacked(rhi, rlo, shi, slo);
Expand Down
60 changes: 60 additions & 0 deletions test/CertManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,38 @@ contract CertManagerTest is Test {
cm.verifyCACertWithHints(rootTwin, rootHash, hints);
}

function test_VerifyCACertWithHints_RejectsSignatureWrapperTagSubstitution() public {
vm.warp(1775145600);
CertManager cm = new CertManager(new P384Verifier());
P384HintCollector collector = new P384HintCollector();

bytes32 rootHash = keccak256(CB0);
bytes memory parentPubKey = cm.loadVerified(rootHash).pubKey;
bytes memory hints = collector.collectCertSignatureHints(CB1, parentPubKey);

bytes memory mutated = bytes.concat(CB1);
(,, Asn1Ptr sigRoot,) = _certSignaturePtrs(mutated);
mutated[sigRoot.header()] = 0x31; // constructed SET with the same r/s children.

vm.expectRevert(CertManager.InvalidAsn1Tag.selector);
cm.verifyCACertWithHints(mutated, rootHash, hints);
}

function test_VerifyCACertWithHints_RejectsTrailingSignatureFields() public {
vm.warp(1775145600);
CertManager cm = new CertManager(new P384Verifier());
P384HintCollector collector = new P384HintCollector();

bytes32 rootHash = keccak256(CB0);
bytes memory parentPubKey = cm.loadVerified(rootHash).pubKey;
bytes memory hints = collector.collectCertSignatureHints(CB1, parentPubKey);

bytes memory mutated = _appendSignatureTrailingField(CB1);

vm.expectRevert(CertManager.InvalidAsn1Tag.selector);
cm.verifyCACertWithHints(mutated, rootHash, hints);
}

function test_VerifyCACertWithHints_RejectsOuterTagSubstitution() public {
vm.warp(1775145600);
CertManager cm = new CertManager(new P384Verifier());
Expand Down Expand Up @@ -338,6 +370,34 @@ contract CertManagerTest is Test {
_writeDerLength(result, sigRoot, _addDelta(sigRoot.length(), delta));
}

function _appendSignatureTrailingField(bytes memory certificate) internal pure returns (bytes memory result) {
(Asn1Ptr root, Asn1Ptr sigPtr, Asn1Ptr sigRoot,) = _certSignaturePtrs(certificate);
bytes memory extraInteger = hex"020100";
int256 delta = int256(extraInteger.length);
result = _insertBytes(certificate, sigRoot.content() + sigRoot.length(), extraInteger);

_writeDerLength(result, root, _addDelta(root.length(), delta));
_writeDerLength(result, sigPtr, _addDelta(sigPtr.length(), delta));
_writeDerLength(result, sigRoot, _addDelta(sigRoot.length(), delta));
}

function _insertBytes(bytes memory input, uint256 offset, bytes memory inserted)
internal
pure
returns (bytes memory result)
{
result = new bytes(input.length + inserted.length);
for (uint256 i = 0; i < offset; ++i) {
result[i] = input[i];
}
for (uint256 i = 0; i < inserted.length; ++i) {
result[offset + i] = inserted[i];
}
for (uint256 i = offset; i < input.length; ++i) {
result[i + inserted.length] = input[i];
}
}

function _certSignaturePtrs(bytes memory certificate)
internal
pure
Expand Down
Loading