Skip to content

Commit

Permalink
Ensure the subject/issuer chain is valid
Browse files Browse the repository at this point in the history
  • Loading branch information
mdehoog committed Dec 8, 2024
1 parent 793b5d5 commit 21b116c
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 5 deletions.
14 changes: 9 additions & 5 deletions src/CertManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,25 +85,27 @@ contract CertManager is ICertManager {

Asn1Ptr root = certificate.root();
Asn1Ptr tbsCertPtr = certificate.firstChildOf(root);
(uint256 notAfter, int256 maxPathLen, bytes memory pubKey) = _parseTbs(certificate, tbsCertPtr, clientCert);
(uint256 notAfter, int256 maxPathLen, bytes32 issuerHash, bytes32 subjectHash, bytes memory pubKey) = _parseTbs(certificate, tbsCertPtr, clientCert);

if (parentCache.pubKey.length != 0 || certHash != ROOT_CA_CERT_HASH) {
require(parentCache.subjectHash == issuerHash, "issuer / subject mismatch");

if (parentCache.maxPathLen > 0 && (maxPathLen < 0 || maxPathLen >= parentCache.maxPathLen)) {
maxPathLen = parentCache.maxPathLen - 1;
}
require(clientCert || parentCache.maxPathLen != 0, "maxPathLen exceeded");
_verifyCertSignature(certificate, tbsCertPtr, parentCache.pubKey);
}

cache = CachedCert({notAfter: notAfter, maxPathLen: maxPathLen, pubKey: pubKey});
cache = CachedCert({notAfter: notAfter, maxPathLen: maxPathLen, subjectHash: subjectHash, pubKey: pubKey});
verified[certHash] = abi.encode(cache);
return cache;
}

function _parseTbs(bytes memory certificate, Asn1Ptr ptr, bool clientCert)
internal
view
returns (uint256 notAfter, int256 maxPathLen, bytes memory pubKey)
returns (uint256 notAfter, int256 maxPathLen, bytes32 issuerHash, bytes32 subjectHash, bytes memory pubKey)
{
Asn1Ptr versionPtr = certificate.firstChildOf(ptr);
Asn1Ptr vPtr = certificate.firstChildOf(versionPtr);
Expand All @@ -115,17 +117,19 @@ contract CertManager is ICertManager {
// as extensions are used in cert, version should be 3 (value 2) as per https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.1
require(version == 2, "version should be 3");

(notAfter, maxPathLen, pubKey) = _parseTbsInner(certificate, sigAlgoPtr, clientCert);
(notAfter, maxPathLen, issuerHash, subjectHash, pubKey) = _parseTbsInner(certificate, sigAlgoPtr, clientCert);
}

function _parseTbsInner(bytes memory certificate, Asn1Ptr sigAlgoPtr, bool clientCert)
internal
view
returns (uint256 notAfter, int256 maxPathLen, bytes memory pubKey)
returns (uint256 notAfter, int256 maxPathLen, bytes32 issuerHash, bytes32 subjectHash, bytes memory pubKey)
{
Asn1Ptr issuerPtr = certificate.nextSiblingOf(sigAlgoPtr);
issuerHash = certificate.keccak(issuerPtr.content(), issuerPtr.length());
Asn1Ptr validityPtr = certificate.nextSiblingOf(issuerPtr);
Asn1Ptr subjectPtr = certificate.nextSiblingOf(validityPtr);
subjectHash = certificate.keccak(subjectPtr.content(), subjectPtr.length());
Asn1Ptr subjectPublicKeyInfoPtr = certificate.nextSiblingOf(subjectPtr);
Asn1Ptr extensionsPtr = certificate.nextSiblingOf(subjectPublicKeyInfoPtr);

Expand Down
1 change: 1 addition & 0 deletions src/ICertManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface ICertManager {
struct CachedCert {
uint256 notAfter;
int256 maxPathLen;
bytes32 subjectHash;
bytes pubKey;
}

Expand Down

0 comments on commit 21b116c

Please sign in to comment.