@@ -17,6 +17,8 @@ contract CertManager is ICertManager {
1717 using LibAsn1Ptr for Asn1Ptr;
1818 using LibBytes for bytes ;
1919
20+ error InvalidAsn1Tag ();
21+
2022 event CertVerified (bytes32 indexed certHash );
2123 event CertRevoked (bytes32 indexed certHash );
2224 event CertUnrevoked (bytes32 indexed certHash );
@@ -163,7 +165,10 @@ contract CertManager is ICertManager {
163165 /// {revokeCerts}; the same value is recorded on-chain when the cert is first verified, so a
164166 /// revocation applies to every byte-encoding of that certificate. Reverts on malformed DER.
165167 function computeCertId (bytes memory cert ) external pure returns (bytes32 ) {
166- Asn1Ptr tbsCertPtr = cert.firstChildOf (cert.root ());
168+ Asn1Ptr root = cert.root ();
169+ _requireAsn1Tag (cert, root, 0x30 );
170+ Asn1Ptr tbsCertPtr = cert.firstChildOf (root);
171+ _requireAsn1Tag (cert, tbsCertPtr, 0x30 );
167172 return _certIdentity (cert, tbsCertPtr);
168173 }
169174
@@ -290,11 +295,17 @@ contract CertManager is ICertManager {
290295 }
291296
292297 Asn1Ptr root = certificate.root ();
298+ _requireAsn1Tag (certificate, root, 0x30 );
293299 require (root.totalLength () == certificate.length , "invalid cert length " );
294300 Asn1Ptr tbsCertPtr = certificate.firstChildOf (root);
301+ _requireAsn1Tag (certificate, tbsCertPtr, 0x30 );
295302 return certificate.keccak (tbsCertPtr.header (), tbsCertPtr.totalLength ());
296303 }
297304
305+ function _requireAsn1Tag (bytes memory der , Asn1Ptr ptr , bytes1 tag ) internal pure {
306+ if (der[ptr.header ()] != tag) revert InvalidAsn1Tag ();
307+ }
308+
298309 function _isPinnedRootAlias (bytes32 certHash , VerifiedCert memory cert ) internal pure returns (bool ) {
299310 return certHash != ROOT_CA_CERT_HASH && cert.ca && cert.subjectHash == ROOT_CA_CERT_SUBJECT_HASH
300311 && cert.pubKey.length == ROOT_CA_CERT_PUB_KEY.length
@@ -308,8 +319,10 @@ contract CertManager is ICertManager {
308319 bytes memory signatureHints
309320 ) internal view returns (VerifiedCert memory cert , bytes32 identity ) {
310321 Asn1Ptr root = certificate.root ();
322+ _requireAsn1Tag (certificate, root, 0x30 );
311323 require (root.totalLength () == certificate.length , "invalid cert length " );
312324 Asn1Ptr tbsCertPtr = certificate.firstChildOf (root);
325+ _requireAsn1Tag (certificate, tbsCertPtr, 0x30 );
313326 (uint64 notAfter , int64 maxPathLen , bytes32 issuerHash , bytes32 subjectHash , bytes memory pubKey ) =
314327 _parseTbs (certificate, tbsCertPtr, ca);
315328
@@ -349,10 +362,13 @@ contract CertManager is ICertManager {
349362 view
350363 returns (uint64 notAfter , int64 maxPathLen , bytes32 issuerHash , bytes32 subjectHash , bytes memory pubKey )
351364 {
365+ _requireAsn1Tag (certificate, ptr, 0x30 );
352366 Asn1Ptr versionPtr = certificate.firstChildOf (ptr);
367+ _requireAsn1Tag (certificate, versionPtr, 0xa0 );
353368 Asn1Ptr vPtr = certificate.firstChildOf (versionPtr);
354369 Asn1Ptr serialPtr = certificate.nextSiblingOf (versionPtr);
355370 Asn1Ptr sigAlgoPtr = certificate.nextSiblingOf (serialPtr);
371+ _requireAsn1Tag (certificate, sigAlgoPtr, 0x30 );
356372
357373 require (certificate.keccak (sigAlgoPtr.content (), sigAlgoPtr.length ()) == CERT_ALGO_OID, "invalid cert sig algo " );
358374 uint256 version = certificate.uintAt (vPtr);
@@ -368,11 +384,15 @@ contract CertManager is ICertManager {
368384 returns (uint64 notAfter , int64 maxPathLen , bytes32 issuerHash , bytes32 subjectHash , bytes memory pubKey )
369385 {
370386 Asn1Ptr issuerPtr = certificate.nextSiblingOf (sigAlgoPtr);
387+ _requireAsn1Tag (certificate, issuerPtr, 0x30 );
371388 issuerHash = certificate.keccak (issuerPtr.content (), issuerPtr.length ());
372389 Asn1Ptr validityPtr = certificate.nextSiblingOf (issuerPtr);
390+ _requireAsn1Tag (certificate, validityPtr, 0x30 );
373391 Asn1Ptr subjectPtr = certificate.nextSiblingOf (validityPtr);
392+ _requireAsn1Tag (certificate, subjectPtr, 0x30 );
374393 subjectHash = certificate.keccak (subjectPtr.content (), subjectPtr.length ());
375394 Asn1Ptr subjectPublicKeyInfoPtr = certificate.nextSiblingOf (subjectPtr);
395+ _requireAsn1Tag (certificate, subjectPublicKeyInfoPtr, 0x30 );
376396 Asn1Ptr extensionsPtr = certificate.nextSiblingOf (subjectPublicKeyInfoPtr);
377397
378398 if (certificate[extensionsPtr.header ()] == 0x81 ) {
@@ -394,7 +414,9 @@ contract CertManager is ICertManager {
394414 pure
395415 returns (bytes memory subjectPubKey )
396416 {
417+ _requireAsn1Tag (certificate, subjectPublicKeyInfoPtr, 0x30 );
397418 Asn1Ptr pubKeyAlgoPtr = certificate.firstChildOf (subjectPublicKeyInfoPtr);
419+ _requireAsn1Tag (certificate, pubKeyAlgoPtr, 0x30 );
398420 Asn1Ptr pubKeyAlgoIdPtr = certificate.firstChildOf (pubKeyAlgoPtr);
399421 Asn1Ptr algoParamsPtr = certificate.nextSiblingOf (pubKeyAlgoIdPtr);
400422 Asn1Ptr subjectPublicKeyPtr = certificate.nextSiblingOf (pubKeyAlgoPtr);
@@ -435,13 +457,15 @@ contract CertManager is ICertManager {
435457 {
436458 require (certificate[extensionsPtr.header ()] == 0xa3 , "invalid extensions " );
437459 extensionsPtr = certificate.firstChildOf (extensionsPtr);
460+ _requireAsn1Tag (certificate, extensionsPtr, 0x30 );
438461 Asn1Ptr extensionPtr = certificate.firstChildOf (extensionsPtr);
439462 uint256 end = extensionsPtr.content () + extensionsPtr.length ();
440463 bool basicConstraintsFound = false ;
441464 bool keyUsageFound = false ;
442465 maxPathLen = - 1 ;
443466
444467 while (true ) {
468+ _requireAsn1Tag (certificate, extensionPtr, 0x30 );
445469 Asn1Ptr oidPtr = certificate.firstChildOf (extensionPtr);
446470 bytes32 oid = certificate.keccak (oidPtr.content (), oidPtr.length ());
447471
@@ -544,6 +568,7 @@ contract CertManager is ICertManager {
544568 bytes memory signatureHints
545569 ) internal view {
546570 Asn1Ptr sigAlgoPtr = certificate.nextSiblingOf (ptr);
571+ _requireAsn1Tag (certificate, sigAlgoPtr, 0x30 );
547572 require (certificate.keccak (sigAlgoPtr.content (), sigAlgoPtr.length ()) == CERT_ALGO_OID, "invalid cert sig algo " );
548573 Asn1Ptr sigPtr = certificate.nextSiblingOf (sigAlgoPtr);
549574 require (sigPtr.header () + sigPtr.totalLength () == certificate.length , "trailing cert fields " );
0 commit comments