@@ -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 (
@@ -405,17 +416,19 @@ contract CertManager is ICertManager {
405416 Asn1Ptr subjectPublicKeyPtr = certificate.nextSiblingOf (pubKeyAlgoPtr);
406417 Asn1Ptr subjectPubKeyPtr = certificate.bitstring (subjectPublicKeyPtr);
407418
408- require (
409- certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) == EC_PUB_KEY_OID,
410- "invalid cert algo id "
411- );
412- require (
413- certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) == SECP_384_R1_OID,
414- "invalid cert algo param "
415- );
419+ if (certificate.keccak (pubKeyAlgoIdPtr.content (), pubKeyAlgoIdPtr.length ()) != EC_PUB_KEY_OID) {
420+ revert InvalidSubjectPublicKey ();
421+ }
422+ if (certificate.keccak (algoParamsPtr.content (), algoParamsPtr.length ()) != SECP_384_R1_OID) {
423+ revert InvalidSubjectPublicKey ();
424+ }
416425
417- uint256 end = subjectPubKeyPtr.content () + subjectPubKeyPtr.length ();
418- subjectPubKey = certificate.slice (end - 96 , 96 );
426+ uint256 keyStart = subjectPubKeyPtr.content ();
427+ uint256 keyLength = subjectPubKeyPtr.length ();
428+ if (keyLength != 97 || keyStart + keyLength > certificate.length || certificate[keyStart] != 0x04 ) {
429+ revert InvalidSubjectPublicKey ();
430+ }
431+ subjectPubKey = certificate.slice (keyStart + 1 , 96 );
419432 }
420433
421434 function _verifyValidity (bytes memory certificate , Asn1Ptr validityPtr ) internal view returns (uint64 notAfter ) {
@@ -438,7 +451,7 @@ contract CertManager is ICertManager {
438451 pure
439452 returns (int64 maxPathLen )
440453 {
441- require (certificate[extensionsPtr.header ()] == 0xa3 , " invalid extensions " );
454+ if (certificate[extensionsPtr.header ()] != 0xa3 ) revert InvalidExtension ( );
442455 extensionsPtr = certificate.firstChildOf (extensionsPtr);
443456 uint256 end = extensionsPtr.content () + extensionsPtr.length ();
444457 Asn1Ptr extensionPtr = _firstChildWithin (certificate, extensionsPtr, end);
@@ -450,21 +463,20 @@ contract CertManager is ICertManager {
450463 uint256 extensionEnd = _requireAsn1NodeWithin (extensionPtr, end);
451464 Asn1Ptr oidPtr = _firstChildWithin (certificate, extensionPtr, extensionEnd);
452465 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
466+ bool recognized = oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID;
453467
454468 Asn1Ptr valuePtr = _nextSiblingWithin (certificate, oidPtr, extensionEnd);
455469
456470 if (certificate[valuePtr.header ()] == 0x01 ) {
457- // skip optional critical bool
458- require ( valuePtr.length () == 1 , " invalid critical bool value " );
471+ if (valuePtr. length () != 1 ) revert InvalidExtension ();
472+ if ( ! recognized && certificate[ valuePtr.content ()] != 0x00 ) revert UnsupportedCriticalExtension ( );
459473 valuePtr = _nextSiblingWithin (certificate, valuePtr, extensionEnd);
460474 }
461475
462476 require (_requireAsn1NodeWithin (valuePtr, extensionEnd) == extensionEnd, "trailing extension fields " );
463477
464- if (oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID) {
465- Asn1Ptr valueNodePtr = valuePtr;
466-
467- valuePtr = certificate.octetString (valueNodePtr);
478+ if (recognized) {
479+ valuePtr = certificate.octetString (valuePtr);
468480
469481 if (oid == BASIC_CONSTRAINTS_OID) {
470482 require (! basicConstraintsFound, "duplicate basicConstraints " );
@@ -483,17 +495,15 @@ contract CertManager is ICertManager {
483495 extensionPtr = _nextSiblingWithin (certificate, extensionPtr, end);
484496 }
485497
486- require (basicConstraintsFound, "basicConstraints not found " );
487- require (keyUsageFound, "keyUsage not found " );
488- require (ca || maxPathLen == - 1 , "maxPathLen must be undefined for client cert " );
498+ if (! basicConstraintsFound || ! keyUsageFound || (! ca && maxPathLen != - 1 )) revert InvalidExtension ();
489499 }
490500
491501 function _verifyBasicConstraintsExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca )
492502 internal
493503 pure
494504 returns (int64 maxPathLen )
495505 {
496- require (certificate[valuePtr.header ()] == 0x30 , " invalid basicConstraints " );
506+ if (certificate[valuePtr.header ()] != 0x30 ) revert InvalidBasicConstraints ( );
497507
498508 maxPathLen = - 1 ;
499509 bool isCA;
@@ -505,37 +515,37 @@ contract CertManager is ICertManager {
505515 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
506516
507517 if (certificate[basicConstraintsPtr.header ()] == 0x01 ) {
508- require (basicConstraintsPtr.length () == 1 , " invalid isCA bool value " );
518+ if (basicConstraintsPtr.length () != 1 ) revert InvalidBasicConstraints ( );
509519 isCA = certificate[basicConstraintsPtr.content ()] == 0xff ;
510520
511521 if (cursor == end) {
512- require (ca == isCA, " isCA must be true for CA certs " );
522+ if (ca != isCA) revert InvalidBasicConstraints ( );
513523 return maxPathLen;
514524 }
515525
516526 basicConstraintsPtr = certificate.nextSiblingOf (basicConstraintsPtr);
517527 cursor = _requireAsn1ChildWithin (basicConstraintsPtr, end);
518528 }
519529
520- require (ca == isCA, " isCA must be true for CA certs " );
530+ if (ca != isCA) revert InvalidBasicConstraints ( );
521531
522532 if (certificate[basicConstraintsPtr.header ()] == 0x02 ) {
523- require (basicConstraintsPtr.length () > 0 , " invalid pathLenConstraint " );
533+ if (basicConstraintsPtr.length () == 0 ) revert InvalidBasicConstraints ( );
524534 maxPathLen = int64 (uint64 (certificate.uintAt (basicConstraintsPtr)));
525535 } else {
526- revert ( " invalid basicConstraints field " );
536+ revert InvalidBasicConstraints ( );
527537 }
528538
529- require (cursor == end, " trailing basicConstraints fields " );
539+ if (cursor != end) revert InvalidBasicConstraints ( );
530540 return maxPathLen;
531541 }
532542
533- require (ca == isCA, " isCA must be true for CA certs " );
543+ if (ca != isCA) revert InvalidBasicConstraints ( );
534544 }
535545
536546 function _requireAsn1ChildWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 childEnd ) {
537547 childEnd = ptr.header () + ptr.totalLength ();
538- require (childEnd <= parentEnd, " basicConstraints out of bounds " );
548+ if (childEnd > parentEnd) revert InvalidBasicConstraints ( );
539549 }
540550
541551 function _requireAsn1NodeWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 nodeEnd ) {
0 commit comments