@@ -17,9 +17,20 @@ contract CertManager is ICertManager {
1717 using LibAsn1Ptr for Asn1Ptr;
1818 using LibBytes for bytes ;
1919
20+ error InvalidExtension ();
21+ error InvalidBasicConstraints ();
22+ error InvalidSubjectPublicKey ();
23+ error UnsupportedCriticalExtension ();
24+ error NotOwner ();
25+ error NotRevoker ();
26+ error IncompleteCertChain ();
27+ error DeprecatedEntrypoint ();
28+ error InvalidOwner ();
29+ error InvalidRevoker ();
30+
2031 event CertVerified (bytes32 indexed certHash );
21- event CertRevoked (bytes32 indexed certHash );
22- event CertUnrevoked (bytes32 indexed certHash );
32+ event CertRevoked (bytes32 indexed certHash , address indexed account );
33+ event CertUnrevoked (bytes32 indexed certHash , address indexed account );
2334 event OwnershipTransferred (address indexed previousOwner , address indexed newOwner );
2435 event RevokerUpdated (address indexed previousRevoker , address indexed newRevoker );
2536
@@ -78,11 +89,11 @@ contract CertManager is ICertManager {
7889 }
7990
8091 function _onlyOwner () internal view {
81- require (msg .sender == owner, " not owner " );
92+ if (msg .sender != owner) revert NotOwner ( );
8293 }
8394
8495 function _onlyRevoker () internal view {
85- require (msg .sender == revoker, " not revoker " );
96+ if (msg .sender != revoker) revert NotRevoker ( );
8697 }
8798
8899 constructor (IP384Verifier p384Verifier_ ) {
@@ -107,12 +118,12 @@ contract CertManager is ICertManager {
107118 /// @notice DEPRECATED — always reverts. The fully on-chain (non-hinted) path is too expensive
108119 /// post-Fusaka and has been removed. Use {verifyCACertWithHints}.
109120 function verifyCACert (bytes memory , bytes32 ) external pure returns (bytes32 ) {
110- revert ( " use hinted cert verification " );
121+ revert DeprecatedEntrypoint ( );
111122 }
112123
113124 /// @notice DEPRECATED — always reverts. Use {verifyClientCertWithHints}.
114125 function verifyClientCert (bytes memory , bytes32 ) external pure returns (VerifiedCert memory ) {
115- revert ( " use hinted cert verification " );
126+ revert DeprecatedEntrypoint ( );
116127 }
117128
118129 /// @notice Verify a CA certificate against its (already-cached) parent and cache the result.
@@ -168,13 +179,13 @@ contract CertManager is ICertManager {
168179 }
169180
170181 function transferOwnership (address newOwner ) external onlyOwner {
171- require (newOwner != address (0 ), " invalid owner " );
182+ if (newOwner == address (0 )) revert InvalidOwner ( );
172183 emit OwnershipTransferred (owner, newOwner);
173184 owner = newOwner;
174185 }
175186
176187 function setRevoker (address newRevoker ) external onlyOwner {
177- require (newRevoker != address (0 ), " invalid revoker " );
188+ if (newRevoker == address (0 )) revert InvalidRevoker ( );
178189 emit RevokerUpdated (revoker, newRevoker);
179190 revoker = newRevoker;
180191 }
@@ -195,12 +206,12 @@ contract CertManager is ICertManager {
195206
196207 function unrevokeCert (bytes32 certId ) external onlyOwner {
197208 revoked[certId] = false ;
198- emit CertUnrevoked (certId);
209+ emit CertUnrevoked (certId, msg . sender );
199210 }
200211
201212 function _revokeCert (bytes32 certId ) internal {
202213 revoked[certId] = true ;
203- emit CertRevoked (certId);
214+ emit CertRevoked (certId, msg . sender );
204215 }
205216
206217 function _requireCanRevoke (bytes32 certId ) internal view {
@@ -235,7 +246,7 @@ contract CertManager is ICertManager {
235246 // Fail closed: a chain that terminates at bytes32(0) without reaching the pinned root is
236247 // broken and must not be treated as a verified, non-revoked chain. Reverting here instead
237248 // of returning silently means revocation safety never depends on upstream guards.
238- revert ( " incomplete cert chain " );
249+ revert IncompleteCertChain ( );
239250 }
240251
241252 function _verifyCert (
@@ -400,17 +411,19 @@ contract CertManager is ICertManager {
400411 Asn1Ptr subjectPublicKeyPtr = certificate.nextSiblingOf (pubKeyAlgoPtr);
401412 Asn1Ptr subjectPubKeyPtr = certificate.bitstring (subjectPublicKeyPtr);
402413
403- require (
404- certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) == EC_PUB_KEY_OID,
405- "invalid cert algo id "
406- );
407- require (
408- certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) == SECP_384_R1_OID,
409- "invalid cert algo param "
410- );
414+ if (certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) != EC_PUB_KEY_OID) {
415+ revert InvalidSubjectPublicKey ();
416+ }
417+ if (certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) != SECP_384_R1_OID) {
418+ revert InvalidSubjectPublicKey ();
419+ }
411420
412- uint256 end = subjectPubKeyPtr.content () + subjectPubKeyPtr.length ();
413- subjectPubKey = certificate.slice (end - 96 , 96 );
421+ uint256 keyStart = subjectPubKeyPtr.content ();
422+ uint256 keyLength = subjectPubKeyPtr.length ();
423+ if (keyLength != 97 || keyStart + keyLength > certificate.length || certificate[keyStart] != 0x04 ) {
424+ revert InvalidSubjectPublicKey ();
425+ }
426+ subjectPubKey = certificate.slice (keyStart + 1 , 96 );
414427 }
415428
416429 function _verifyValidity (bytes memory certificate , Asn1Ptr validityPtr ) internal view returns (uint64 notAfter ) {
@@ -433,7 +446,7 @@ contract CertManager is ICertManager {
433446 pure
434447 returns (int64 maxPathLen )
435448 {
436- require (certificate[extensionsPtr.header ()] == 0xa3 , " invalid extensions " );
449+ if (certificate[extensionsPtr.header ()] != 0xa3 ) revert InvalidExtension ( );
437450 extensionsPtr = certificate.firstChildOf (extensionsPtr);
438451 Asn1Ptr extensionPtr = certificate.firstChildOf (extensionsPtr);
439452 uint256 end = extensionsPtr.content () + extensionsPtr.length ();
@@ -444,16 +457,16 @@ contract CertManager is ICertManager {
444457 while (true ) {
445458 Asn1Ptr oidPtr = certificate.firstChildOf (extensionPtr);
446459 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
460+ Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
461+ bool recognized = oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID;
447462
448- if (oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID) {
449- Asn1Ptr valuePtr = certificate.nextSiblingOf (oidPtr);
450-
451- if (certificate[valuePtr.header ()] == 0x01 ) {
452- // skip optional critical bool
453- require (valuePtr.length () == 1 , "invalid critical bool value " );
454- valuePtr = certificate.nextSiblingOf (valuePtr);
455- }
463+ if (certificate[valuePtr.header ()] == 0x01 ) {
464+ if (valuePtr.length () != 1 ) revert InvalidExtension ();
465+ if (! recognized && certificate[valuePtr.content ()] != 0x00 ) revert UnsupportedCriticalExtension ();
466+ valuePtr = certificate.nextSiblingOf (valuePtr);
467+ }
456468
469+ if (recognized) {
457470 valuePtr = certificate.octetString (valuePtr);
458471
459472 if (oid == BASIC_CONSTRAINTS_OID) {
@@ -471,17 +484,15 @@ contract CertManager is ICertManager {
471484 extensionPtr = certificate.nextSiblingOf (extensionPtr);
472485 }
473486
474- require (basicConstraintsFound, "basicConstraints not found " );
475- require (keyUsageFound, "keyUsage not found " );
476- require (ca || maxPathLen == - 1 , "maxPathLen must be undefined for client cert " );
487+ if (! basicConstraintsFound || ! keyUsageFound || (! ca && maxPathLen != - 1 )) revert InvalidExtension ();
477488 }
478489
479490 function _verifyBasicConstraintsExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca )
480491 internal
481492 pure
482493 returns (int64 maxPathLen )
483494 {
484- require (certificate[valuePtr.header ()] == 0x30 , " invalid basicConstraints " );
495+ if (certificate[valuePtr.header ()] != 0x30 ) revert InvalidBasicConstraints ( );
485496
486497 maxPathLen = - 1 ;
487498 bool isCA;
@@ -493,37 +504,37 @@ contract CertManager is ICertManager {
493504 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
494505
495506 if (certificate[basicConstraintsPtr.header ()] == 0x01 ) {
496- require (basicConstraintsPtr.length () == 1 , " invalid isCA bool value " );
507+ if (basicConstraintsPtr.length () != 1 ) revert InvalidBasicConstraints ( );
497508 isCA = certificate[basicConstraintsPtr.content ()] == 0xff ;
498509
499510 if (cursor == end) {
500- require (ca == isCA, " isCA must be true for CA certs " );
511+ if (ca != isCA) revert InvalidBasicConstraints ( );
501512 return maxPathLen;
502513 }
503514
504515 basicConstraintsPtr = certificate.nextSiblingOf (basicConstraintsPtr);
505516 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
506517 }
507518
508- require (ca == isCA, " isCA must be true for CA certs " );
519+ if (ca != isCA) revert InvalidBasicConstraints ( );
509520
510521 if (certificate[basicConstraintsPtr.header ()] == 0x02 ) {
511- require (basicConstraintsPtr.length () > 0 , " invalid pathLenConstraint " );
522+ if (basicConstraintsPtr.length () == 0 ) revert InvalidBasicConstraints ( );
512523 maxPathLen = int64 (uint64 (certificate.uintAt (basicConstraintsPtr)));
513524 } else {
514- revert ( " invalid basicConstraints field " );
525+ revert InvalidBasicConstraints ( );
515526 }
516527
517- require (cursor == end, " trailing basicConstraints fields " );
528+ if (cursor != end) revert InvalidBasicConstraints ( );
518529 return maxPathLen;
519530 }
520531
521- require (ca == isCA, " isCA must be true for CA certs " );
532+ if (ca != isCA) revert InvalidBasicConstraints ( );
522533 }
523534
524535 function _requireAsn1ChildWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 childEnd ) {
525536 childEnd = ptr.header () + ptr.totalLength ();
526- require (childEnd <= parentEnd, " basicConstraints out of bounds " );
537+ if (childEnd > parentEnd) revert InvalidBasicConstraints ( );
527538 }
528539
529540 function _verifyKeyUsageExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca ) internal pure {
0 commit comments