@@ -308,7 +308,7 @@ contract CertManager is ICertManager {
308308
309309 Asn1Ptr root = certificate.root ();
310310 _requireAsn1Tag (certificate, root, 0x30 );
311- require (root.totalLength () == certificate.length , " invalid cert length " );
311+ if (root.totalLength () != certificate.length ) revert Asn1Decode. InvalidAsn1Length ( );
312312 Asn1Ptr tbsCertPtr = certificate.firstChildOf (root);
313313 _requireAsn1Tag (certificate, tbsCertPtr, 0x30 );
314314 return certificate.keccak (tbsCertPtr.header (), tbsCertPtr.totalLength ());
@@ -331,7 +331,7 @@ contract CertManager is ICertManager {
331331 bytes memory signatureHints
332332 ) internal view returns (VerifiedCert memory cert , bytes32 identity ) {
333333 Asn1Ptr root = certificate.root ();
334- require (root.totalLength () == certificate.length , " invalid cert length " );
334+ if (root.totalLength () != certificate.length ) revert Asn1Decode. InvalidAsn1Length ( );
335335 Asn1Ptr tbsCertPtr = certificate.firstChildOf (root);
336336 (uint64 notAfter , int64 maxPathLen , bytes32 issuerHash , bytes32 subjectHash , bytes memory pubKey ) =
337337 _parseTbs (certificate, tbsCertPtr, ca);
@@ -372,27 +372,20 @@ contract CertManager is ICertManager {
372372 view
373373 returns (uint64 notAfter , int64 maxPathLen , bytes32 issuerHash , bytes32 subjectHash , bytes memory pubKey )
374374 {
375- Asn1Ptr sigAlgoPtr = _verifyTbsHeader (certificate, ptr);
376-
377- (notAfter, maxPathLen, issuerHash, subjectHash, pubKey) =
378- _parseTbsInner (certificate, sigAlgoPtr, ca, ptr.content () + ptr.length ());
379- }
380-
381- function _verifyTbsHeader (bytes memory certificate , Asn1Ptr ptr ) internal pure returns (Asn1Ptr sigAlgoPtr ) {
382375 _requireAsn1Tag (certificate, ptr, 0x30 );
383376 Asn1Ptr versionPtr = certificate.firstChildOf (ptr);
384377 _requireAsn1Tag (certificate, versionPtr, 0xa0 );
385- Asn1Ptr vPtr = certificate.firstChildOf (versionPtr);
386- Asn1Ptr serialPtr = certificate.nextSiblingOf (versionPtr);
387- sigAlgoPtr = certificate.nextSiblingOf (serialPtr);
378+ Asn1Ptr sigAlgoPtr = certificate.nextSiblingOf (certificate.nextSiblingOf (versionPtr));
388379 _requireAsn1Tag (certificate, sigAlgoPtr, 0x30 );
389380
390381 if (certificate.keccak (sigAlgoPtr.content (), sigAlgoPtr.length ()) != CERT_ALGO_OID) {
391382 revert InvalidCertAlgorithm ();
392383 }
393- uint256 version = certificate.uintAt (vPtr);
394384 // 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
395- if (version != 2 ) revert InvalidCertVersion ();
385+ if (certificate.uintAt (certificate.firstChildOf (versionPtr)) != 2 ) revert InvalidCertVersion ();
386+
387+ (notAfter, maxPathLen, issuerHash, subjectHash, pubKey) =
388+ _parseTbsInner (certificate, sigAlgoPtr, ca, ptr.content () + ptr.length ());
396389 }
397390
398391 function _parseTbsInner (bytes memory certificate , Asn1Ptr sigAlgoPtr , bool ca , uint256 tbsEnd )
@@ -420,7 +413,7 @@ contract CertManager is ICertManager {
420413 // skip optional subjectUniqueID
421414 extensionsPtr = certificate.nextSiblingOf (extensionsPtr);
422415 }
423- if (_requireAsn1NodeWithin ( extensionsPtr, tbsEnd ) != tbsEnd) revert Asn1Decode.InvalidAsn1Length ();
416+ if (extensionsPtr. content () + extensionsPtr. length ( ) != tbsEnd) revert Asn1Decode.InvalidAsn1Length ();
424417
425418 notAfter = _verifyValidity (certificate, validityPtr);
426419 maxPathLen = _verifyExtensions (certificate, extensionsPtr, ca);
@@ -484,21 +477,22 @@ contract CertManager is ICertManager {
484477 maxPathLen = - 1 ;
485478
486479 while (true ) {
487- uint256 extensionEnd = _requireAsn1NodeWithin (extensionPtr, end);
480+ uint256 extensionEnd = extensionPtr.content () + extensionPtr.length ();
481+ if (extensionEnd > end) revert InvalidExtension ();
488482 _requireAsn1Tag (certificate, extensionPtr, 0x30 );
489483 Asn1Ptr oidPtr = certificate.firstChildOf (extensionPtr);
490484 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
491485 bool recognized = oid == BASIC_CONSTRAINTS_OID || oid == KEY_USAGE_OID;
492486
493- Asn1Ptr valuePtr = _nextSiblingWithin ( certificate, oidPtr, extensionEnd );
487+ Asn1Ptr valuePtr = certificate. nextSiblingOf ( oidPtr);
494488
495489 if (certificate[valuePtr.header ()] == 0x01 ) {
496490 if (valuePtr.length () != 1 ) revert InvalidExtension ();
497491 if (! recognized && certificate[valuePtr.content ()] != 0x00 ) revert UnsupportedCriticalExtension ();
498- valuePtr = _nextSiblingWithin ( certificate, valuePtr, extensionEnd );
492+ valuePtr = certificate. nextSiblingOf ( valuePtr);
499493 }
500494
501- if (_requireAsn1NodeWithin ( valuePtr, extensionEnd ) != extensionEnd) revert InvalidExtension ();
495+ if (valuePtr. content () + valuePtr. length ( ) != extensionEnd) revert InvalidExtension ();
502496
503497 if (recognized) {
504498 valuePtr = certificate.octetString (valuePtr);
@@ -517,7 +511,7 @@ contract CertManager is ICertManager {
517511 if (extensionEnd == end) {
518512 break ;
519513 }
520- extensionPtr = _nextSiblingWithin ( certificate, extensionPtr, end );
514+ extensionPtr = certificate. nextSiblingOf ( extensionPtr);
521515 }
522516
523517 if (! basicConstraintsFound || ! keyUsageFound || (! ca && maxPathLen != - 1 )) revert InvalidExtension ();
@@ -573,28 +567,14 @@ contract CertManager is ICertManager {
573567 if (childEnd > parentEnd) revert InvalidBasicConstraints ();
574568 }
575569
576- function _requireAsn1NodeWithin (Asn1Ptr ptr , uint256 parentEnd ) internal pure returns (uint256 nodeEnd ) {
577- nodeEnd = ptr.header () + ptr.totalLength ();
578- if (nodeEnd > parentEnd) revert Asn1Decode.InvalidAsn1Length ();
579- }
580-
581- function _nextSiblingWithin (bytes memory der , Asn1Ptr ptr , uint256 parentEnd )
582- internal
583- pure
584- returns (Asn1Ptr sibling )
585- {
586- sibling = der.nextSiblingOf (ptr);
587- _requireAsn1NodeWithin (sibling, parentEnd);
588- }
589-
590570 function _verifyKeyUsageExtension (bytes memory certificate , Asn1Ptr valuePtr , bool ca ) internal pure {
591571 uint256 value = certificate.bitstringUintAt (valuePtr);
592572 // X.509 KeyUsage bits are MSB-first. bitstringUintAt keeps the first KeyUsage octet in the
593573 // low byte, so these masks continue to target the same bits for one- or multi-octet values.
594574 if (ca) {
595- require (value & 0x04 == 0x04 , " CertSign must be present " );
575+ if (value & 0x04 != 0x04 ) revert InvalidExtension ( );
596576 } else {
597- require (value & 0x80 == 0x80 , " DigitalSignature must be present " );
577+ if (value & 0x80 != 0x80 ) revert InvalidExtension ( );
598578 }
599579 }
600580
@@ -610,7 +590,7 @@ contract CertManager is ICertManager {
610590 revert InvalidCertAlgorithm ();
611591 }
612592 Asn1Ptr sigPtr = certificate.nextSiblingOf (sigAlgoPtr);
613- require (sigPtr.header () + sigPtr.totalLength () == certificate.length , " trailing cert fields " );
593+ if (sigPtr.header () + sigPtr.totalLength () != certificate.length ) revert Asn1Decode. InvalidAsn1Length ( );
614594
615595 bytes memory hash = Sha2Ext.sha384 (certificate, ptr.header (), ptr.totalLength ());
616596 bytes memory sigPacked = _certSignature (certificate, sigPtr);
@@ -621,8 +601,15 @@ contract CertManager is ICertManager {
621601 function _certSignature (bytes memory certificate , Asn1Ptr sigPtr ) internal pure returns (bytes memory sigPacked ) {
622602 Asn1Ptr sigBPtr = certificate.bitstring (sigPtr);
623603 Asn1Ptr sigRoot = certificate.rootOf (sigBPtr);
604+ _requireAsn1Tag (certificate, sigRoot, 0x30 );
624605 Asn1Ptr sigRPtr = certificate.firstChildOf (sigRoot);
625606 Asn1Ptr sigSPtr = certificate.nextSiblingOf (sigRPtr);
607+ if (
608+ sigRoot.header () + sigRoot.totalLength () != sigBPtr.content () + sigBPtr.length ()
609+ || sigSPtr.header () + sigSPtr.totalLength () != sigRoot.content () + sigRoot.length ()
610+ ) {
611+ revert InvalidAsn1Tag ();
612+ }
626613 (uint128 rhi , uint256 rlo ) = certificate.uint384At (sigRPtr);
627614 (uint128 shi , uint256 slo ) = certificate.uint384At (sigSPtr);
628615 sigPacked = abi.encodePacked (rhi, rlo, shi, slo);
0 commit comments