@@ -18,10 +18,20 @@ contract CertManager is ICertManager {
1818 using LibBytes for bytes ;
1919
2020 error InvalidAsn1Tag ();
21+ error InvalidExtension ();
22+ error InvalidBasicConstraints ();
23+ error InvalidSubjectPublicKey ();
24+ error UnsupportedCriticalExtension ();
25+ error NotOwner ();
26+ error NotRevoker ();
27+ error IncompleteCertChain ();
28+ error DeprecatedEntrypoint ();
29+ error InvalidOwner ();
30+ error InvalidRevoker ();
2131
2232 event CertVerified (bytes32 indexed certHash );
23- event CertRevoked (bytes32 indexed certHash );
24- event CertUnrevoked (bytes32 indexed certHash );
33+ event CertRevoked (bytes32 indexed certHash , address indexed account );
34+ event CertUnrevoked (bytes32 indexed certHash , address indexed account );
2535 event OwnershipTransferred (address indexed previousOwner , address indexed newOwner );
2636 event RevokerUpdated (address indexed previousRevoker , address indexed newRevoker );
2737
@@ -80,11 +90,11 @@ contract CertManager is ICertManager {
8090 }
8191
8292 function _onlyOwner () internal view {
83- require (msg .sender == owner, " not owner " );
93+ if (msg .sender != owner) revert NotOwner ( );
8494 }
8595
8696 function _onlyRevoker () internal view {
87- require (msg .sender == revoker, " not revoker " );
97+ if (msg .sender != revoker) revert NotRevoker ( );
8898 }
8999
90100 constructor (IP384Verifier p384Verifier_ ) {
@@ -109,12 +119,12 @@ contract CertManager is ICertManager {
109119 /// @notice DEPRECATED — always reverts. The fully on-chain (non-hinted) path is too expensive
110120 /// post-Fusaka and has been removed. Use {verifyCACertWithHints}.
111121 function verifyCACert (bytes memory , bytes32 ) external pure returns (bytes32 ) {
112- revert ( " use hinted cert verification " );
122+ revert DeprecatedEntrypoint ( );
113123 }
114124
115125 /// @notice DEPRECATED — always reverts. Use {verifyClientCertWithHints}.
116126 function verifyClientCert (bytes memory , bytes32 ) external pure returns (VerifiedCert memory ) {
117- revert ( " use hinted cert verification " );
127+ revert DeprecatedEntrypoint ( );
118128 }
119129
120130 /// @notice Verify a CA certificate against its (already-cached) parent and cache the result.
@@ -173,13 +183,13 @@ contract CertManager is ICertManager {
173183 }
174184
175185 function transferOwnership (address newOwner ) external onlyOwner {
176- require (newOwner != address (0 ), " invalid owner " );
186+ if (newOwner == address (0 )) revert InvalidOwner ( );
177187 emit OwnershipTransferred (owner, newOwner);
178188 owner = newOwner;
179189 }
180190
181191 function setRevoker (address newRevoker ) external onlyOwner {
182- require (newRevoker != address (0 ), " invalid revoker " );
192+ if (newRevoker == address (0 )) revert InvalidRevoker ( );
183193 emit RevokerUpdated (revoker, newRevoker);
184194 revoker = newRevoker;
185195 }
@@ -200,12 +210,12 @@ contract CertManager is ICertManager {
200210
201211 function unrevokeCert (bytes32 certId ) external onlyOwner {
202212 revoked[certId] = false ;
203- emit CertUnrevoked (certId);
213+ emit CertUnrevoked (certId, msg . sender );
204214 }
205215
206216 function _revokeCert (bytes32 certId ) internal {
207217 revoked[certId] = true ;
208- emit CertRevoked (certId);
218+ emit CertRevoked (certId, msg . sender );
209219 }
210220
211221 function _requireCanRevoke (bytes32 certId ) internal view {
@@ -240,7 +250,7 @@ contract CertManager is ICertManager {
240250 // Fail closed: a chain that terminates at bytes32(0) without reaching the pinned root is
241251 // broken and must not be treated as a verified, non-revoked chain. Reverting here instead
242252 // of returning silently means revocation safety never depends on upstream guards.
243- revert ( " incomplete cert chain " );
253+ revert IncompleteCertChain ( );
244254 }
245255
246256 function _verifyCert (
@@ -419,17 +429,19 @@ contract CertManager is ICertManager {
419429 Asn1Ptr subjectPublicKeyPtr = certificate.nextSiblingOf (pubKeyAlgoPtr);
420430 Asn1Ptr subjectPubKeyPtr = certificate.bitstring (subjectPublicKeyPtr);
421431
422- require (
423- certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) == EC_PUB_KEY_OID,
424- "invalid cert algo id "
425- );
426- require (
427- certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) == SECP_384_R1_OID,
428- "invalid cert algo param "
429- );
432+ if (certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) != EC_PUB_KEY_OID) {
433+ revert InvalidSubjectPublicKey ();
434+ }
435+ if (certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) != SECP_384_R1_OID) {
436+ revert InvalidSubjectPublicKey ();
437+ }
430438
431- uint256 end = subjectPubKeyPtr.content () + subjectPubKeyPtr.length ();
432- subjectPubKey = certificate.slice (end - 96 , 96 );
439+ uint256 keyStart = subjectPubKeyPtr.content ();
440+ uint256 keyLength = subjectPubKeyPtr.length ();
441+ if (keyLength != 97 || keyStart + keyLength > certificate.length || certificate[keyStart] != 0x04 ) {
442+ revert InvalidSubjectPublicKey ();
443+ }
444+ subjectPubKey = certificate.slice (keyStart + 1 , 96 );
433445 }
434446
435447 function _verifyValidity (bytes memory certificate , Asn1Ptr validityPtr ) internal view returns (uint64 notAfter ) {
@@ -452,7 +464,7 @@ contract CertManager is ICertManager {
452464 pure
453465 returns (int64 maxPathLen )
454466 {
455- require (certificate[extensionsPtr.header ()] == 0xa3 , " invalid extensions " );
467+ if (certificate[extensionsPtr.header ()] != 0xa3 ) revert InvalidExtension ( );
456468 extensionsPtr = certificate.firstChildOf (extensionsPtr);
457469 _requireAsn1Tag (certificate, extensionsPtr, 0x30 );
458470 Asn1Ptr extensionPtr = certificate.firstChildOf (extensionsPtr);
@@ -465,16 +477,16 @@ contract CertManager is ICertManager {
465477 _requireAsn1Tag (certificate, extensionPtr, 0x30 );
466478 Asn1Ptr oidPtr = certificate.firstChildOf (extensionPtr);
467479 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
480+ Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
481+ bool recognized = oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID;
468482
469- if (oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID) {
470- Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
471-
472- if (certificate[valuePtr.header ()] == 0x01 ) {
473- // skip optional critical bool
474- require (valuePtr.length () == 1 , "invalid critical bool value " );
475- valuePtr = certificate.nextSiblingOf (valuePtr);
476- }
483+ if (certificate[valuePtr.header ()] == 0x01 ) {
484+ if (valuePtr.length () != 1 ) revert InvalidExtension ();
485+ if (! recognized && certificate[valuePtr.content ()] != 0x00 ) revert UnsupportedCriticalExtension ();
486+ valuePtr = certificate.nextSiblingOf (valuePtr);
487+ }
477488
489+ if (recognized) {
478490 valuePtr = certificate.octetString (valuePtr);
479491
480492 if (oid == BASIC_CONSTRAINTS_OID) {
@@ -492,17 +504,15 @@ contract CertManager is ICertManager {
492504 extensionPtr = certificate.nextSiblingOf (extensionPtr);
493505 }
494506
495- require (basicConstraintsFound, "basicConstraints not found " );
496- require (keyUsageFound, "keyUsage not found " );
497- require (ca || maxPathLen == - 1 , "maxPathLen must be undefined for client cert " );
507+ if (! basicConstraintsFound || ! keyUsageFound || (! ca && maxPathLen != - 1 )) revert InvalidExtension ();
498508 }
499509
500510 function _verifyBasicConstraintsExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca )
501511 internal
502512 pure
503513 returns (int64 maxPathLen )
504514 {
505- require (certificate[valuePtr.header ()] == 0x30 , " invalid basicConstraints " );
515+ if (certificate[valuePtr.header ()] != 0x30 ) revert InvalidBasicConstraints ( );
506516
507517 maxPathLen = - 1 ;
508518 bool isCA;
@@ -514,37 +524,37 @@ contract CertManager is ICertManager {
514524 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
515525
516526 if (certificate[basicConstraintsPtr.header ()] == 0x01 ) {
517- require (basicConstraintsPtr.length () == 1 , " invalid isCA bool value " );
527+ if (basicConstraintsPtr.length () != 1 ) revert InvalidBasicConstraints ( );
518528 isCA = certificate[basicConstraintsPtr.content ()] == 0xff ;
519529
520530 if (cursor == end) {
521- require (ca == isCA, " isCA must be true for CA certs " );
531+ if (ca != isCA) revert InvalidBasicConstraints ( );
522532 return maxPathLen;
523533 }
524534
525535 basicConstraintsPtr = certificate.nextSiblingOf (basicConstraintsPtr);
526536 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
527537 }
528538
529- require (ca == isCA, " isCA must be true for CA certs " );
539+ if (ca != isCA) revert InvalidBasicConstraints ( );
530540
531541 if (certificate[basicConstraintsPtr.header ()] == 0x02 ) {
532- require (basicConstraintsPtr.length () > 0 , " invalid pathLenConstraint " );
542+ if (basicConstraintsPtr.length () == 0 ) revert InvalidBasicConstraints ( );
533543 maxPathLen = int64 (uint64 (certificate.uintAt (basicConstraintsPtr)));
534544 } else {
535- revert ( " invalid basicConstraints field " );
545+ revert InvalidBasicConstraints ( );
536546 }
537547
538- require (cursor == end, " trailing basicConstraints fields " );
548+ if (cursor != end) revert InvalidBasicConstraints ( );
539549 return maxPathLen;
540550 }
541551
542- require (ca == isCA, " isCA must be true for CA certs " );
552+ if (ca != isCA) revert InvalidBasicConstraints ( );
543553 }
544554
545555 function _requireAsn1ChildWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 childEnd ) {
546556 childEnd = ptr.header () + ptr.totalLength ();
547- require (childEnd <= parentEnd, " basicConstraints out of bounds " );
557+ if (childEnd > parentEnd) revert InvalidBasicConstraints ( );
548558 }
549559
550560 function _verifyKeyUsageExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca ) internal pure {
0 commit comments