@@ -18,10 +18,20 @@ contract CertManager is ICertManager {
1818 using LibBytes for bytes ;
1919
2020 error InvalidCertSignature ();
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.
@@ -170,13 +180,13 @@ contract CertManager is ICertManager {
170180 }
171181
172182 function transferOwnership (address newOwner ) external onlyOwner {
173- require (newOwner != address (0 ), " invalid owner " );
183+ if (newOwner == address (0 )) revert InvalidOwner ( );
174184 emit OwnershipTransferred (owner, newOwner);
175185 owner = newOwner;
176186 }
177187
178188 function setRevoker (address newRevoker ) external onlyOwner {
179- require (newRevoker != address (0 ), " invalid revoker " );
189+ if (newRevoker == address (0 )) revert InvalidRevoker ( );
180190 emit RevokerUpdated (revoker, newRevoker);
181191 revoker = newRevoker;
182192 }
@@ -197,12 +207,12 @@ contract CertManager is ICertManager {
197207
198208 function unrevokeCert (bytes32 certId ) external onlyOwner {
199209 revoked[certId] = false ;
200- emit CertUnrevoked (certId);
210+ emit CertUnrevoked (certId, msg . sender );
201211 }
202212
203213 function _revokeCert (bytes32 certId ) internal {
204214 revoked[certId] = true ;
205- emit CertRevoked (certId);
215+ emit CertRevoked (certId, msg . sender );
206216 }
207217
208218 function _requireCanRevoke (bytes32 certId ) internal view {
@@ -237,7 +247,7 @@ contract CertManager is ICertManager {
237247 // Fail closed: a chain that terminates at bytes32(0) without reaching the pinned root is
238248 // broken and must not be treated as a verified, non-revoked chain. Reverting here instead
239249 // of returning silently means revocation safety never depends on upstream guards.
240- revert ( " incomplete cert chain " );
250+ revert IncompleteCertChain ( );
241251 }
242252
243253 function _verifyCert (
@@ -402,17 +412,19 @@ contract CertManager is ICertManager {
402412 Asn1Ptr subjectPublicKeyPtr = certificate.nextSiblingOf (pubKeyAlgoPtr);
403413 Asn1Ptr subjectPubKeyPtr = certificate.bitstring (subjectPublicKeyPtr);
404414
405- require (
406- certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) == EC_PUB_KEY_OID,
407- "invalid cert algo id "
408- );
409- require (
410- certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) == SECP_384_R1_OID,
411- "invalid cert algo param "
412- );
415+ if (certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) != EC_PUB_KEY_OID) {
416+ revert InvalidSubjectPublicKey ();
417+ }
418+ if (certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) != SECP_384_R1_OID) {
419+ revert InvalidSubjectPublicKey ();
420+ }
413421
414- uint256 end = subjectPubKeyPtr.content () + subjectPubKeyPtr.length ();
415- subjectPubKey = certificate.slice (end - 96 , 96 );
422+ uint256 keyStart = subjectPubKeyPtr.content ();
423+ uint256 keyLength = subjectPubKeyPtr.length ();
424+ if (keyLength != 97 || keyStart + keyLength > certificate.length || certificate[keyStart] != 0x04 ) {
425+ revert InvalidSubjectPublicKey ();
426+ }
427+ subjectPubKey = certificate.slice (keyStart + 1 , 96 );
416428 }
417429
418430 function _verifyValidity (bytes memory certificate , Asn1Ptr validityPtr ) internal view returns (uint64 notAfter ) {
@@ -435,7 +447,7 @@ contract CertManager is ICertManager {
435447 pure
436448 returns (int64 maxPathLen )
437449 {
438- require (certificate[extensionsPtr.header ()] == 0xa3 , " invalid extensions " );
450+ if (certificate[extensionsPtr.header ()] != 0xa3 ) revert InvalidExtension ( );
439451 extensionsPtr = certificate.firstChildOf (extensionsPtr);
440452 Asn1Ptr extensionPtr = certificate.firstChildOf (extensionsPtr);
441453 uint256 end = extensionsPtr.content () + extensionsPtr.length ();
@@ -446,16 +458,16 @@ contract CertManager is ICertManager {
446458 while (true ) {
447459 Asn1Ptr oidPtr = certificate.firstChildOf (extensionPtr);
448460 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
461+ Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
462+ bool recognized = oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID;
449463
450- if (oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID) {
451- Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
452-
453- if (certificate[valuePtr.header ()] == 0x01 ) {
454- // skip optional critical bool
455- require (valuePtr.length () == 1 , "invalid critical bool value " );
456- valuePtr = certificate.nextSiblingOf (valuePtr);
457- }
464+ if (certificate[valuePtr.header ()] == 0x01 ) {
465+ if (valuePtr.length () != 1 ) revert InvalidExtension ();
466+ if (! recognized && certificate[valuePtr.content ()] != 0x00 ) revert UnsupportedCriticalExtension ();
467+ valuePtr = certificate.nextSiblingOf (valuePtr);
468+ }
458469
470+ if (recognized) {
459471 valuePtr = certificate.octetString (valuePtr);
460472
461473 if (oid == BASIC_CONSTRAINTS_OID) {
@@ -473,17 +485,15 @@ contract CertManager is ICertManager {
473485 extensionPtr = certificate.nextSiblingOf (extensionPtr);
474486 }
475487
476- require (basicConstraintsFound, "basicConstraints not found " );
477- require (keyUsageFound, "keyUsage not found " );
478- require (ca || maxPathLen == - 1 , "maxPathLen must be undefined for client cert " );
488+ if (! basicConstraintsFound || ! keyUsageFound || (! ca && maxPathLen != - 1 )) revert InvalidExtension ();
479489 }
480490
481491 function _verifyBasicConstraintsExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca )
482492 internal
483493 pure
484494 returns (int64 maxPathLen )
485495 {
486- require (certificate[valuePtr.header ()] == 0x30 , " invalid basicConstraints " );
496+ if (certificate[valuePtr.header ()] != 0x30 ) revert InvalidBasicConstraints ( );
487497
488498 maxPathLen = - 1 ;
489499 bool isCA;
@@ -495,37 +505,37 @@ contract CertManager is ICertManager {
495505 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
496506
497507 if (certificate[basicConstraintsPtr.header ()] == 0x01 ) {
498- require (basicConstraintsPtr.length () == 1 , " invalid isCA bool value " );
508+ if (basicConstraintsPtr.length () != 1 ) revert InvalidBasicConstraints ( );
499509 isCA = certificate[basicConstraintsPtr.content ()] == 0xff ;
500510
501511 if (cursor == end) {
502- require (ca == isCA, " isCA must be true for CA certs " );
512+ if (ca != isCA) revert InvalidBasicConstraints ( );
503513 return maxPathLen;
504514 }
505515
506516 basicConstraintsPtr = certificate.nextSiblingOf (basicConstraintsPtr);
507517 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
508518 }
509519
510- require (ca == isCA, " isCA must be true for CA certs " );
520+ if (ca != isCA) revert InvalidBasicConstraints ( );
511521
512522 if (certificate[basicConstraintsPtr.header ()] == 0x02 ) {
513- require (basicConstraintsPtr.length () > 0 , " invalid pathLenConstraint " );
523+ if (basicConstraintsPtr.length () == 0 ) revert InvalidBasicConstraints ( );
514524 maxPathLen = int64 (uint64 (certificate.uintAt (basicConstraintsPtr)));
515525 } else {
516- revert ( " invalid basicConstraints field " );
526+ revert InvalidBasicConstraints ( );
517527 }
518528
519- require (cursor == end, " trailing basicConstraints fields " );
529+ if (cursor != end) revert InvalidBasicConstraints ( );
520530 return maxPathLen;
521531 }
522532
523- require (ca == isCA, " isCA must be true for CA certs " );
533+ if (ca != isCA) revert InvalidBasicConstraints ( );
524534 }
525535
526536 function _requireAsn1ChildWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 childEnd ) {
527537 childEnd = ptr.header () + ptr.totalLength ();
528- require (childEnd <= parentEnd, " basicConstraints out of bounds " );
538+ if (childEnd > parentEnd) revert InvalidBasicConstraints ( );
529539 }
530540
531541 function _verifyKeyUsageExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca ) internal pure {
0 commit comments