Remove pki/tag.h

This is a very thin wrapper over CBS_ASN1_* constants, dating from when
the library wanted to avoid as strongly depending on BoringSSL. That's
long stopped being the case, so we may as well just use the underlying
constants. A tad less C++-y, but I don't think the wrapper is buying us
much.

Update-Note: pki/tag.h no longer exists. Use CBS_ASN1_TAG instead of
bssl::der::Tag and CBS_ASN1_* instead of bssl::der::k*.

Change-Id: I09f3f65b406d1a8fe60bfbe1a56d3e485ae84d97
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66067
Commit-Queue: David Benjamin <davidben@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/pki/certificate_policies.cc b/pki/certificate_policies.cc
index 5a6df34..198e348 100644
--- a/pki/certificate_policies.cc
+++ b/pki/certificate_policies.cc
@@ -12,7 +12,6 @@
 #include "input.h"
 #include "parse_values.h"
 #include "parser.h"
-#include "tag.h"
 
 namespace bssl {
 
@@ -64,7 +63,7 @@
     }
     //      policyQualifierId  PolicyQualifierId,
     der::Input qualifier_oid;
-    if (!policy_information_parser.ReadTag(der::kOid, &qualifier_oid)) {
+    if (!policy_information_parser.ReadTag(CBS_ASN1_OBJECT, &qualifier_oid)) {
       return false;
     }
     if (restrict_to_known_qualifiers &&
@@ -164,7 +163,7 @@
     }
     //      policyIdentifier   CertPolicyId,
     der::Input policy_oid;
-    if (!policy_information_parser.ReadTag(der::kOid, &policy_oid)) {
+    if (!policy_information_parser.ReadTag(CBS_ASN1_OBJECT, &policy_oid)) {
       return false;
     }
 
@@ -273,7 +272,7 @@
   }
 
   std::optional<der::Input> require_value;
-  if (!sequence_parser.ReadOptionalTag(der::ContextSpecificPrimitive(0),
+  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 0,
                                        &require_value)) {
     return false;
   }
@@ -289,7 +288,7 @@
   }
 
   std::optional<der::Input> inhibit_value;
-  if (!sequence_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1),
+  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                        &inhibit_value)) {
     return false;
   }
@@ -364,10 +363,12 @@
     }
 
     ParsedPolicyMapping mapping;
-    if (!mapping_parser.ReadTag(der::kOid, &mapping.issuer_domain_policy)) {
+    if (!mapping_parser.ReadTag(CBS_ASN1_OBJECT,
+                                &mapping.issuer_domain_policy)) {
       return false;
     }
-    if (!mapping_parser.ReadTag(der::kOid, &mapping.subject_domain_policy)) {
+    if (!mapping_parser.ReadTag(CBS_ASN1_OBJECT,
+                                &mapping.subject_domain_policy)) {
       return false;
     }
 
diff --git a/pki/crl.cc b/pki/crl.cc
index cc9c878..63e1cc6 100644
--- a/pki/crl.cc
+++ b/pki/crl.cc
@@ -6,6 +6,7 @@
 #include <iterator>
 
 #include <openssl/base.h>
+#include <openssl/bytestring.h>
 
 #include "cert_errors.h"
 #include "crl.h"
@@ -14,7 +15,6 @@
 #include "parser.h"
 #include "revocation_util.h"
 #include "signature_algorithm.h"
-#include "tag.h"
 #include "verify_name_match.h"
 #include "verify_signed_data.h"
 
@@ -31,7 +31,7 @@
   der::Parser parser(name_tlv);
   der::Input name_rdn;
   bssl::CertErrors unused_errors;
-  return parser.ReadTag(der::kSequence, &name_rdn) &&
+  return parser.ReadTag(CBS_ASN1_SEQUENCE, &name_rdn) &&
          NormalizeName(name_rdn, out_normalized_name, &unused_errors) &&
          !parser.HasMore();
 }
@@ -104,7 +104,7 @@
   //         version                 Version OPTIONAL,
   //                                      -- if present, MUST be v2
   std::optional<der::Input> version_der;
-  if (!tbs_parser.ReadOptionalTag(der::kInteger, &version_der)) {
+  if (!tbs_parser.ReadOptionalTag(CBS_ASN1_INTEGER, &version_der)) {
     return false;
   }
   if (version_der.has_value()) {
@@ -139,12 +139,12 @@
   }
 
   //         nextUpdate              Time OPTIONAL,
-  der::Tag maybe_next_update_tag;
+  CBS_ASN1_TAG maybe_next_update_tag;
   der::Input unused_next_update_input;
   if (tbs_parser.PeekTagAndValue(&maybe_next_update_tag,
                                  &unused_next_update_input) &&
-      (maybe_next_update_tag == der::kUtcTime ||
-       maybe_next_update_tag == der::kGeneralizedTime)) {
+      (maybe_next_update_tag == CBS_ASN1_UTCTIME ||
+       maybe_next_update_tag == CBS_ASN1_GENERALIZEDTIME)) {
     der::GeneralizedTime next_update_time;
     if (!ReadUTCOrGeneralizedTime(&tbs_parser, &next_update_time)) {
       return false;
@@ -156,10 +156,10 @@
 
   //         revokedCertificates     SEQUENCE OF SEQUENCE  { ... } OPTIONAL,
   der::Input unused_revoked_certificates;
-  der::Tag maybe_revoked_certifigates_tag;
+  CBS_ASN1_TAG maybe_revoked_certifigates_tag;
   if (tbs_parser.PeekTagAndValue(&maybe_revoked_certifigates_tag,
                                  &unused_revoked_certificates) &&
-      maybe_revoked_certifigates_tag == der::kSequence) {
+      maybe_revoked_certifigates_tag == CBS_ASN1_SEQUENCE) {
     der::Input revoked_certificates_tlv;
     if (!tbs_parser.ReadRawTLV(&revoked_certificates_tlv)) {
       return false;
@@ -171,8 +171,9 @@
 
   //         crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
   //                                       -- if present, version MUST be v2
-  if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
-                                  &out->crl_extensions_tlv)) {
+  if (!tbs_parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
+          &out->crl_extensions_tlv)) {
     return false;
   }
   if (out->crl_extensions_tlv.has_value()) {
@@ -216,7 +217,7 @@
   //  distributionPoint          [0] DistributionPointName OPTIONAL,
   std::optional<der::Input> distribution_point;
   if (!idp_parser.ReadOptionalTag(
-          der::kTagContextSpecific | der::kTagConstructed | 0,
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
           &distribution_point)) {
     return false;
   }
@@ -228,7 +229,7 @@
     //        nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
     std::optional<der::Input> der_full_name;
     if (!dp_name_parser.ReadOptionalTag(
-            der::kTagContextSpecific | der::kTagConstructed | 0,
+            CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
             &der_full_name)) {
       return false;
     }
@@ -253,7 +254,7 @@
 
   //  onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE,
   std::optional<der::Input> only_contains_user_certs;
-  if (!idp_parser.ReadOptionalTag(der::kTagContextSpecific | 1,
+  if (!idp_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                   &only_contains_user_certs)) {
     return false;
   }
@@ -270,7 +271,7 @@
 
   //  onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE,
   std::optional<der::Input> only_contains_ca_certs;
-  if (!idp_parser.ReadOptionalTag(der::kTagContextSpecific | 2,
+  if (!idp_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2,
                                   &only_contains_ca_certs)) {
     return false;
   }
@@ -343,7 +344,8 @@
 
     der::Input revoked_cert_serial_number;
     //              userCertificate         CertificateSerialNumber,
-    if (!crl_entry_parser.ReadTag(der::kInteger, &revoked_cert_serial_number)) {
+    if (!crl_entry_parser.ReadTag(CBS_ASN1_INTEGER,
+                                  &revoked_cert_serial_number)) {
       return CRLRevocationStatus::UNKNOWN;
     }
 
diff --git a/pki/extended_key_usage.cc b/pki/extended_key_usage.cc
index a5d007f..1aeeb6a 100644
--- a/pki/extended_key_usage.cc
+++ b/pki/extended_key_usage.cc
@@ -4,9 +4,10 @@
 
 #include "extended_key_usage.h"
 
+#include <openssl/bytestring.h>
+
 #include "input.h"
 #include "parser.h"
-#include "tag.h"
 
 namespace bssl {
 
@@ -27,7 +28,7 @@
   }
   while (sequence_parser.HasMore()) {
     der::Input eku_oid;
-    if (!sequence_parser.ReadTag(der::kOid, &eku_oid)) {
+    if (!sequence_parser.ReadTag(CBS_ASN1_OBJECT, &eku_oid)) {
       // The SEQUENCE OF must contain only KeyPurposeIds (OIDs).
       return false;
     }
diff --git a/pki/general_names.cc b/pki/general_names.cc
index 74874ba..c446287 100644
--- a/pki/general_names.cc
+++ b/pki/general_names.cc
@@ -5,6 +5,7 @@
 #include "general_names.h"
 
 #include <openssl/base.h>
+#include <openssl/bytestring.h>
 
 #include <climits>
 #include <cstring>
@@ -15,7 +16,6 @@
 #include "ip_util.h"
 #include "parser.h"
 #include "string_util.h"
-#include "tag.h"
 
 namespace bssl {
 
@@ -52,7 +52,7 @@
   // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
   der::Parser parser(general_names_tlv);
   der::Input sequence_value;
-  if (!parser.ReadTag(der::kSequence, &sequence_value)) {
+  if (!parser.ReadTag(CBS_ASN1_SEQUENCE, &sequence_value)) {
     errors->AddError(kFailedReadingGeneralNames);
     return nullptr;
   }
@@ -101,17 +101,17 @@
     GeneralNames *subtrees, CertErrors *errors) {
   BSSL_CHECK(errors);
   der::Parser parser(input);
-  der::Tag tag;
+  CBS_ASN1_TAG tag;
   der::Input value;
   if (!parser.ReadTagAndValue(&tag, &value)) {
     return false;
   }
   GeneralNameTypes name_type = GENERAL_NAME_NONE;
-  if (tag == der::ContextSpecificConstructed(0)) {
+  if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
     // otherName                       [0]     OtherName,
     name_type = GENERAL_NAME_OTHER_NAME;
     subtrees->other_names.push_back(value);
-  } else if (tag == der::ContextSpecificPrimitive(1)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 1)) {
     // rfc822Name                      [1]     IA5String,
     name_type = GENERAL_NAME_RFC822_NAME;
     const std::string_view s = BytesAsStringView(value);
@@ -120,7 +120,7 @@
       return false;
     }
     subtrees->rfc822_names.push_back(s);
-  } else if (tag == der::ContextSpecificPrimitive(2)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 2)) {
     // dNSName                         [2]     IA5String,
     name_type = GENERAL_NAME_DNS_NAME;
     const std::string_view s = BytesAsStringView(value);
@@ -129,11 +129,11 @@
       return false;
     }
     subtrees->dns_names.push_back(s);
-  } else if (tag == der::ContextSpecificConstructed(3)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3)) {
     // x400Address                     [3]     ORAddress,
     name_type = GENERAL_NAME_X400_ADDRESS;
     subtrees->x400_addresses.push_back(value);
-  } else if (tag == der::ContextSpecificConstructed(4)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4)) {
     // directoryName                   [4]     Name,
     name_type = GENERAL_NAME_DIRECTORY_NAME;
     // Name is a CHOICE { rdnSequence  RDNSequence }, therefore the SEQUENCE
@@ -141,15 +141,16 @@
     // only the value portion.
     der::Parser name_parser(value);
     der::Input name_value;
-    if (!name_parser.ReadTag(der::kSequence, &name_value) || parser.HasMore()) {
+    if (!name_parser.ReadTag(CBS_ASN1_SEQUENCE, &name_value) ||
+        parser.HasMore()) {
       return false;
     }
     subtrees->directory_names.push_back(name_value);
-  } else if (tag == der::ContextSpecificConstructed(5)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 5)) {
     // ediPartyName                    [5]     EDIPartyName,
     name_type = GENERAL_NAME_EDI_PARTY_NAME;
     subtrees->edi_party_names.push_back(value);
-  } else if (tag == der::ContextSpecificPrimitive(6)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 6)) {
     // uniformResourceIdentifier       [6]     IA5String,
     name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER;
     const std::string_view s = BytesAsStringView(value);
@@ -158,7 +159,7 @@
       return false;
     }
     subtrees->uniform_resource_identifiers.push_back(s);
-  } else if (tag == der::ContextSpecificPrimitive(7)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 7)) {
     // iPAddress                       [7]     OCTET STRING,
     name_type = GENERAL_NAME_IP_ADDRESS;
     if (ip_address_type == GeneralNames::IP_ADDRESS_ONLY) {
@@ -201,7 +202,7 @@
       }
       subtrees->ip_address_ranges.emplace_back(addr, mask);
     }
-  } else if (tag == der::ContextSpecificPrimitive(8)) {
+  } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 8)) {
     // registeredID                    [8]     OBJECT IDENTIFIER }
     name_type = GENERAL_NAME_REGISTERED_ID;
     subtrees->registered_ids.push_back(value);
diff --git a/pki/name_constraints.cc b/pki/name_constraints.cc
index 73d87aa..1ce9a8f 100644
--- a/pki/name_constraints.cc
+++ b/pki/name_constraints.cc
@@ -7,9 +7,11 @@
 #include <limits.h>
 
 #include <memory>
+#include <optional>
 
 #include <openssl/base.h>
-#include <optional>
+#include <openssl/bytestring.h>
+
 #include "cert_errors.h"
 #include "common_cert_errors.h"
 #include "general_names.h"
@@ -17,7 +19,6 @@
 #include "ip_util.h"
 #include "parser.h"
 #include "string_util.h"
-#include "tag.h"
 #include "verify_name_match.h"
 
 namespace bssl {
@@ -317,8 +318,9 @@
   }
 
   std::optional<der::Input> permitted_subtrees_value;
-  if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
-                                       &permitted_subtrees_value)) {
+  if (!sequence_parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
+          &permitted_subtrees_value)) {
     return false;
   }
   if (permitted_subtrees_value &&
@@ -331,8 +333,9 @@
       (is_critical ? GENERAL_NAME_ALL_TYPES : kSupportedNameTypes);
 
   std::optional<der::Input> excluded_subtrees_value;
-  if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
-                                       &excluded_subtrees_value)) {
+  if (!sequence_parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
+          &excluded_subtrees_value)) {
     return false;
   }
   if (excluded_subtrees_value &&
diff --git a/pki/ocsp.cc b/pki/ocsp.cc
index 49076e9..03d6c21 100644
--- a/pki/ocsp.cc
+++ b/pki/ocsp.cc
@@ -51,16 +51,16 @@
   if (!parser.ReadRawTLV(&sigalg_tlv)) {
     return false;
   }
-  if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm))) {
+  if (!ParseHashAlgorithm(sigalg_tlv, &out->hash_algorithm)) {
     return false;
   }
-  if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash))) {
+  if (!parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->issuer_name_hash)) {
     return false;
   }
-  if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash))) {
+  if (!parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->issuer_key_hash)) {
     return false;
   }
-  if (!parser.ReadTag(der::kInteger, &(out->serial_number))) {
+  if (!parser.ReadTag(CBS_ASN1_INTEGER, &out->serial_number)) {
     return false;
   }
   CertErrors errors;
@@ -89,15 +89,16 @@
   }
 
   der::Input reason_input;
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input,
-                              &(out->has_reason))) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &reason_input,
+          &(out->has_reason))) {
     return false;
   }
   if (out->has_reason) {
     der::Parser reason_parser(reason_input);
     der::Input reason_value_input;
     uint8_t reason_value;
-    if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input)) {
+    if (!reason_parser.ReadTag(CBS_ASN1_ENUMERATED, &reason_value_input)) {
       return false;
     }
     if (!der::ParseUint8(reason_value_input, &reason_value)) {
@@ -132,21 +133,22 @@
 // UnknownInfo ::= NULL
 bool ParseCertStatus(der::Input raw_tlv, OCSPCertStatus *out) {
   der::Parser parser(raw_tlv);
-  der::Tag status_tag;
+  CBS_ASN1_TAG status_tag;
   der::Input status;
   if (!parser.ReadTagAndValue(&status_tag, &status)) {
     return false;
   }
 
   out->has_reason = false;
-  if (status_tag == der::ContextSpecificPrimitive(0)) {
+  if (status_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
     out->status = OCSPRevocationStatus::GOOD;
-  } else if (status_tag == der::ContextSpecificConstructed(1)) {
+  } else if (status_tag ==
+             (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
     out->status = OCSPRevocationStatus::REVOKED;
     if (!ParseRevokedInfo(status, out)) {
       return false;
     }
-  } else if (status_tag == der::ContextSpecificPrimitive(2)) {
+  } else if (status_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 2)) {
     out->status = OCSPRevocationStatus::UNKNOWN;
   } else {
     return false;
@@ -203,8 +205,9 @@
   }
 
   der::Input next_update_input;
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
-                              &next_update_input, &(out->has_next_update))) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
+          &next_update_input, &(out->has_next_update))) {
     return false;
   }
   if (out->has_next_update) {
@@ -217,8 +220,9 @@
     }
   }
 
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
-                              &(out->extensions), &(out->has_extensions))) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
+          &(out->extensions), &(out->has_extensions))) {
     return false;
   }
 
@@ -236,19 +240,19 @@
 // }
 bool ParseResponderID(der::Input raw_tlv, OCSPResponseData::ResponderID *out) {
   der::Parser parser(raw_tlv);
-  der::Tag id_tag;
+  CBS_ASN1_TAG id_tag;
   der::Input id_input;
   if (!parser.ReadTagAndValue(&id_tag, &id_input)) {
     return false;
   }
 
-  if (id_tag == der::ContextSpecificConstructed(1)) {
+  if (id_tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
     out->type = OCSPResponseData::ResponderType::NAME;
     out->name = id_input;
-  } else if (id_tag == der::ContextSpecificConstructed(2)) {
+  } else if (id_tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2)) {
     der::Parser key_parser(id_input);
     der::Input key_hash;
-    if (!key_parser.ReadTag(der::kOctetString, &key_hash)) {
+    if (!key_parser.ReadTag(CBS_ASN1_OCTETSTRING, &key_hash)) {
       return false;
     }
     if (key_parser.HasMore()) {
@@ -287,8 +291,9 @@
 
   der::Input version_input;
   bool version_present;
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
-                              &version_input, &version_present)) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &version_input,
+          &version_present)) {
     return false;
   }
 
@@ -335,8 +340,9 @@
     out->responses.push_back(single_response);
   }
 
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
-                              &(out->extensions), &(out->has_extensions))) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
+          &(out->extensions), &(out->has_extensions))) {
     return false;
   }
 
@@ -385,8 +391,9 @@
   }
   out->signature = signature.value();
   der::Input certs_input;
-  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input,
-                              &(out->has_certs))) {
+  if (!parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &certs_input,
+          &(out->has_certs))) {
     return false;
   }
 
@@ -435,7 +442,7 @@
 
   der::Input response_status_input;
   uint8_t response_status;
-  if (!parser.ReadTag(der::kEnumerated, &response_status_input)) {
+  if (!parser.ReadTag(CBS_ASN1_ENUMERATED, &response_status_input)) {
     return false;
   }
   if (!der::ParseUint8(response_status_input, &response_status)) {
@@ -453,8 +460,9 @@
   if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
     der::Parser outer_bytes_parser;
     der::Parser bytes_parser;
-    if (!parser.ReadConstructed(der::ContextSpecificConstructed(0),
-                                &outer_bytes_parser)) {
+    if (!parser.ReadConstructed(
+            CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
+            &outer_bytes_parser)) {
       return false;
     }
     if (!outer_bytes_parser.ReadSequence(&bytes_parser)) {
@@ -465,7 +473,7 @@
     }
 
     der::Input type_oid;
-    if (!bytes_parser.ReadTag(der::kOid, &type_oid)) {
+    if (!bytes_parser.ReadTag(CBS_ASN1_OBJECT, &type_oid)) {
       return false;
     }
     if (type_oid != der::Input(kBasicOCSPResponseOid)) {
@@ -475,7 +483,7 @@
     // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
     // encoding of BasicOCSPResponse.
     der::Input response;
-    if (!bytes_parser.ReadTag(der::kOctetString, &response)) {
+    if (!bytes_parser.ReadTag(CBS_ASN1_OCTETSTRING, &response)) {
       return false;
     }
     if (!ParseBasicOCSPResponse(response, out)) {
@@ -607,9 +615,9 @@
     case OCSPResponseData::ResponderType::NAME: {
       der::Input name_rdn;
       der::Input cert_rdn;
-      if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) ||
+      if (!der::Parser(id.name).ReadTag(CBS_ASN1_SEQUENCE, &name_rdn) ||
           !der::Parser(cert->tbs().subject_tlv)
-               .ReadTag(der::kSequence, &cert_rdn)) {
+               .ReadTag(CBS_ASN1_SEQUENCE, &cert_rdn)) {
         return false;
       }
       return VerifyNameMatch(name_rdn, cert_rdn);
diff --git a/pki/parse_certificate.cc b/pki/parse_certificate.cc
index de910d3..5e2ff88 100644
--- a/pki/parse_certificate.cc
+++ b/pki/parse_certificate.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include <openssl/base.h>
+#include <openssl/bytestring.h>
 
 #include "cert_error_params.h"
 #include "cert_errors.h"
@@ -152,7 +153,7 @@
   der::Parser parser(dp_name);
   std::optional<der::Input> der_full_name;
   if (!parser.ReadOptionalTag(
-          der::kTagContextSpecific | der::kTagConstructed | 0,
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
           &der_full_name)) {
     return false;
   }
@@ -168,7 +169,7 @@
   }
 
   if (!parser.ReadOptionalTag(
-          der::kTagContextSpecific | der::kTagConstructed | 1,
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
           &distribution_point
                ->distribution_point_name_relative_to_crl_issuer)) {
     return false;
@@ -201,7 +202,7 @@
   //  distributionPoint       [0]     DistributionPointName OPTIONAL,
   std::optional<der::Input> distribution_point_name;
   if (!distrib_point_parser.ReadOptionalTag(
-          der::kTagContextSpecific | der::kTagConstructed | 0,
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
           &distribution_point_name)) {
     return false;
   }
@@ -213,14 +214,14 @@
   }
 
   //  reasons                 [1]     ReasonFlags OPTIONAL,
-  if (!distrib_point_parser.ReadOptionalTag(der::kTagContextSpecific | 1,
+  if (!distrib_point_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                             &distribution_point.reasons)) {
     return false;
   }
 
   //  cRLIssuer               [2]     GeneralNames OPTIONAL }
   if (!distrib_point_parser.ReadOptionalTag(
-          der::kTagContextSpecific | der::kTagConstructed | 2,
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2,
           &distribution_point.crl_issuer)) {
     return false;
   }
@@ -290,17 +291,17 @@
 
 bool ReadUTCOrGeneralizedTime(der::Parser *parser, der::GeneralizedTime *out) {
   der::Input value;
-  der::Tag tag;
+  CBS_ASN1_TAG tag;
 
   if (!parser->ReadTagAndValue(&tag, &value)) {
     return false;
   }
 
-  if (tag == der::kUtcTime) {
+  if (tag == CBS_ASN1_UTCTIME) {
     return der::ParseUTCTime(value, out);
   }
 
-  if (tag == der::kGeneralizedTime) {
+  if (tag == CBS_ASN1_GENERALIZEDTIME) {
     return der::ParseGeneralizedTime(value, out);
   }
 
@@ -443,8 +444,8 @@
 
   //        version         [0]  EXPLICIT Version DEFAULT v1,
   std::optional<der::Input> version;
-  if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
-                                  &version)) {
+  if (!tbs_parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &version)) {
     errors->AddError(kFailedReadingVersion);
     return false;
   }
@@ -464,7 +465,7 @@
   }
 
   //        serialNumber         CertificateSerialNumber,
-  if (!tbs_parser.ReadTag(der::kInteger, &out->serial_number)) {
+  if (!tbs_parser.ReadTag(CBS_ASN1_INTEGER, &out->serial_number)) {
     errors->AddError(kFailedReadingSerialNumber);
     return false;
   }
@@ -516,7 +517,7 @@
   //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
   //                             -- If present, version MUST be v2 or v3
   std::optional<der::Input> issuer_unique_id;
-  if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1),
+  if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                   &issuer_unique_id)) {
     errors->AddError(kFailedReadingIssuerUniqueId);
     return false;
@@ -537,7 +538,7 @@
   //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
   //                             -- If present, version MUST be v2 or v3
   std::optional<der::Input> subject_unique_id;
-  if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(2),
+  if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2,
                                   &subject_unique_id)) {
     errors->AddError(kFailedReadingSubjectUniqueId);
     return false;
@@ -557,8 +558,9 @@
 
   //        extensions      [3]  EXPLICIT Extensions OPTIONAL
   //                             -- If present, version MUST be v3
-  if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(3),
-                                  &out->extensions_tlv)) {
+  if (!tbs_parser.ReadOptionalTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3,
+          &out->extensions_tlv)) {
     errors->AddError(kFailedReadingExtensions);
     return false;
   }
@@ -616,7 +618,7 @@
   }
 
   //            extnID      OBJECT IDENTIFIER,
-  if (!extension_parser.ReadTag(der::kOid, &out->oid)) {
+  if (!extension_parser.ReadTag(CBS_ASN1_OBJECT, &out->oid)) {
     return false;
   }
 
@@ -624,7 +626,8 @@
   out->critical = false;
   bool has_critical;
   der::Input critical;
-  if (!extension_parser.ReadOptionalTag(der::kBool, &critical, &has_critical)) {
+  if (!extension_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &critical,
+                                        &has_critical)) {
     return false;
   }
   if (has_critical) {
@@ -637,7 +640,7 @@
   }
 
   //            extnValue   OCTET STRING
-  if (!extension_parser.ReadTag(der::kOctetString, &out->value)) {
+  if (!extension_parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->value)) {
     return false;
   }
 
@@ -733,7 +736,7 @@
   out->is_ca = false;
   bool has_ca;
   der::Input ca;
-  if (!sequence_parser.ReadOptionalTag(der::kBool, &ca, &has_ca)) {
+  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &ca, &has_ca)) {
     return false;
   }
   if (has_ca) {
@@ -748,7 +751,7 @@
 
   //         pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
   der::Input encoded_path_len;
-  if (!sequence_parser.ReadOptionalTag(der::kInteger, &encoded_path_len,
+  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_INTEGER, &encoded_path_len,
                                        &out->has_path_len)) {
     return false;
   }
@@ -830,7 +833,7 @@
 
     //            accessMethod          OBJECT IDENTIFIER,
     if (!access_description_sequence_parser.ReadTag(
-            der::kOid, &access_description.access_method_oid)) {
+            CBS_ASN1_OBJECT, &access_description.access_method_oid)) {
       return false;
     }
 
@@ -862,7 +865,7 @@
 
   for (const auto &access_description : access_descriptions) {
     der::Parser access_location_parser(access_description.access_location);
-    der::Tag access_location_tag;
+    CBS_ASN1_TAG access_location_tag;
     der::Input access_location_value;
     if (!access_location_parser.ReadTagAndValue(&access_location_tag,
                                                 &access_location_value)) {
@@ -870,7 +873,7 @@
     }
 
     // GeneralName ::= CHOICE {
-    if (access_location_tag == der::ContextSpecificPrimitive(6)) {
+    if (access_location_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 6)) {
       // uniformResourceIdentifier       [6]     IA5String,
       std::string_view uri = BytesAsStringView(access_location_value);
       if (!bssl::string_util::IsAscii(uri)) {
@@ -956,21 +959,21 @@
   // error? RFC 5280 doesn't explicitly say it.
 
   //       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
-  if (!aki_parser.ReadOptionalTag(der::ContextSpecificPrimitive(0),
+  if (!aki_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 0,
                                   &authority_key_identifier->key_identifier)) {
     return false;
   }
 
   //       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
   if (!aki_parser.ReadOptionalTag(
-          der::ContextSpecificConstructed(1),
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
           &authority_key_identifier->authority_cert_issuer)) {
     return false;
   }
 
   //       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
   if (!aki_parser.ReadOptionalTag(
-          der::ContextSpecificPrimitive(2),
+          CBS_ASN1_CONTEXT_SPECIFIC | 2,
           &authority_key_identifier->authority_cert_serial_number)) {
     return false;
   }
@@ -997,7 +1000,7 @@
   //
   //    KeyIdentifier ::= OCTET STRING
   der::Parser extension_value_parser(extension_value);
-  if (!extension_value_parser.ReadTag(der::kOctetString,
+  if (!extension_value_parser.ReadTag(CBS_ASN1_OCTETSTRING,
                                       subject_key_identifier)) {
     return false;
   }
diff --git a/pki/parse_name.cc b/pki/parse_name.cc
index dca76b4..f1b3a91 100644
--- a/pki/parse_name.cc
+++ b/pki/parse_name.cc
@@ -8,6 +8,7 @@
 
 #include <openssl/bytestring.h>
 #include <openssl/mem.h>
+
 #include "parse_values.h"
 #include "string_util.h"
 
@@ -31,18 +32,18 @@
 
 bool X509NameAttribute::ValueAsString(std::string *out) const {
   switch (value_tag) {
-    case der::kTeletexString:
+    case CBS_ASN1_T61STRING:
       return der::ParseTeletexStringAsLatin1(value, out);
-    case der::kIA5String:
+    case CBS_ASN1_IA5STRING:
       return der::ParseIA5String(value, out);
-    case der::kPrintableString:
+    case CBS_ASN1_PRINTABLESTRING:
       return der::ParsePrintableString(value, out);
-    case der::kUtf8String:
+    case CBS_ASN1_UTF8STRING:
       *out = BytesAsStringView(value);
       return true;
-    case der::kUniversalString:
+    case CBS_ASN1_UNIVERSALSTRING:
       return der::ParseUniversalString(value, out);
-    case der::kBmpString:
+    case CBS_ASN1_BMPSTRING:
       return der::ParseBmpString(value, out);
     default:
       return false;
@@ -52,7 +53,7 @@
 bool X509NameAttribute::ValueAsStringWithUnsafeOptions(
     PrintableStringHandling printable_string_handling, std::string *out) const {
   if (printable_string_handling == PrintableStringHandling::kAsUTF8Hack &&
-      value_tag == der::kPrintableString) {
+      value_tag == CBS_ASN1_PRINTABLESTRING) {
     *out = BytesAsStringView(value);
     return true;
   }
@@ -61,15 +62,15 @@
 
 bool X509NameAttribute::ValueAsStringUnsafe(std::string *out) const {
   switch (value_tag) {
-    case der::kIA5String:
-    case der::kPrintableString:
-    case der::kTeletexString:
-    case der::kUtf8String:
+    case CBS_ASN1_IA5STRING:
+    case CBS_ASN1_PRINTABLESTRING:
+    case CBS_ASN1_T61STRING:
+    case CBS_ASN1_UTF8STRING:
       *out = BytesAsStringView(value);
       return true;
-    case der::kUniversalString:
+    case CBS_ASN1_UNIVERSALSTRING:
       return der::ParseUniversalString(value, out);
-    case der::kBmpString:
+    case CBS_ASN1_BMPSTRING:
       return der::ParseBmpString(value, out);
     default:
       assert(0);  // NOTREACHED
@@ -137,7 +138,7 @@
 
     // If we have non-printable characters in a TeletexString, we hex encode
     // since we don't handle Teletex control codes.
-    if (nonprintable && value_tag == der::kTeletexString) {
+    if (nonprintable && value_tag == CBS_ASN1_T61STRING) {
       value_string = "#" + bssl::string_util::HexEncode(value);
     }
   }
@@ -154,12 +155,12 @@
     }
     // Read the attribute type, which must be an OBJECT IDENTIFIER.
     der::Input type;
-    if (!attr_type_and_value.ReadTag(der::kOid, &type)) {
+    if (!attr_type_and_value.ReadTag(CBS_ASN1_OBJECT, &type)) {
       return false;
     }
 
     // Read the attribute value.
-    der::Tag tag;
+    CBS_ASN1_TAG tag;
     der::Input value;
     if (!attr_type_and_value.ReadTagAndValue(&tag, &value)) {
       return false;
@@ -182,7 +183,7 @@
 bool ParseName(der::Input name_tlv, RDNSequence *out) {
   der::Parser name_parser(name_tlv);
   der::Input name_value;
-  if (!name_parser.ReadTag(der::kSequence, &name_value)) {
+  if (!name_parser.ReadTag(CBS_ASN1_SEQUENCE, &name_value)) {
     return false;
   }
   return ParseNameValue(name_value, out);
@@ -192,7 +193,7 @@
   der::Parser rdn_sequence_parser(name_value);
   while (rdn_sequence_parser.HasMore()) {
     der::Parser rdn_parser;
-    if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) {
+    if (!rdn_sequence_parser.ReadConstructed(CBS_ASN1_SET, &rdn_parser)) {
       return false;
     }
     RelativeDistinguishedName type_and_values;
diff --git a/pki/parse_name.h b/pki/parse_name.h
index 837f326..be5c53e 100644
--- a/pki/parse_name.h
+++ b/pki/parse_name.h
@@ -8,10 +8,10 @@
 #include <vector>
 
 #include <openssl/base.h>
+#include <openssl/bytestring.h>
 
 #include "input.h"
 #include "parser.h"
-#include "tag.h"
 
 namespace bssl {
 
@@ -65,7 +65,7 @@
 //     value AttributeValue
 // }
 struct OPENSSL_EXPORT X509NameAttribute {
-  X509NameAttribute(der::Input in_type, der::Tag in_value_tag,
+  X509NameAttribute(der::Input in_type, CBS_ASN1_TAG in_value_tag,
                     der::Input in_value)
       : type(in_type), value_tag(in_value_tag), value(in_value) {}
 
@@ -106,7 +106,7 @@
   [[nodiscard]] bool AsRFC2253String(std::string *out) const;
 
   der::Input type;
-  der::Tag value_tag;
+  CBS_ASN1_TAG value_tag;
   der::Input value;
 };
 
diff --git a/pki/parse_name_unittest.cc b/pki/parse_name_unittest.cc
index 9858121..ceef9c2 100644
--- a/pki/parse_name_unittest.cc
+++ b/pki/parse_name_unittest.cc
@@ -36,7 +36,7 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kIA5String, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_IA5STRING, der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Foo bar", result_unsafe);
@@ -49,7 +49,7 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0xFF, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kIA5String, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_IA5STRING, der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Fo\377 bar", result_unsafe);
@@ -61,7 +61,8 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kPrintableString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_PRINTABLESTRING,
+                          der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Foo bar", result_unsafe);
@@ -74,7 +75,8 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0x5f, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kPrintableString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_PRINTABLESTRING,
+                          der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Fo_ bar", result_unsafe);
@@ -86,7 +88,8 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0x5f, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kPrintableString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_PRINTABLESTRING,
+                          der::Input(der));
   std::string result;
   ASSERT_FALSE(value.ValueAsStringWithUnsafeOptions(
       X509NameAttribute::PrintableStringHandling::kDefault, &result));
@@ -99,7 +102,7 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kTeletexString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_T61STRING, der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Foo bar", result_unsafe);
@@ -112,7 +115,7 @@
   const uint8_t der[] = {
       0x46, 0x6f, 0xd6, 0x20, 0x62, 0x61, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kTeletexString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_T61STRING, der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("Fo\xd6 bar", result_unsafe);
@@ -125,7 +128,7 @@
   const uint8_t der[] = {
       0x00, 0x66, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x61, 0x00, 0x72,
   };
-  X509NameAttribute value(der::Input(), der::kBmpString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_BMPSTRING, der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("foobar", result_unsafe);
@@ -137,7 +140,7 @@
 // BmpString must encode characters in pairs of 2 bytes.
 TEST(ParseNameTest, ConvertInvalidBmpString) {
   const uint8_t der[] = {0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x72};
-  X509NameAttribute value(der::Input(), der::kBmpString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_BMPSTRING, der::Input(der));
   std::string result;
   ASSERT_FALSE(value.ValueAsStringUnsafe(&result));
   ASSERT_FALSE(value.ValueAsString(&result));
@@ -147,7 +150,8 @@
   const uint8_t der[] = {0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x6f,
                          0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x62,
                          0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x72};
-  X509NameAttribute value(der::Input(), der::kUniversalString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_UNIVERSALSTRING,
+                          der::Input(der));
   std::string result_unsafe;
   ASSERT_TRUE(value.ValueAsStringUnsafe(&result_unsafe));
   ASSERT_EQ("foobar", result_unsafe);
@@ -159,7 +163,8 @@
 // UniversalString must encode characters in pairs of 4 bytes.
 TEST(ParseNameTest, ConvertInvalidUniversalString) {
   const uint8_t der[] = {0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72};
-  X509NameAttribute value(der::Input(), der::kUniversalString, der::Input(der));
+  X509NameAttribute value(der::Input(), CBS_ASN1_UNIVERSALSTRING,
+                          der::Input(der));
   std::string result;
   ASSERT_FALSE(value.ValueAsStringUnsafe(&result));
   ASSERT_FALSE(value.ValueAsString(&result));
diff --git a/pki/parsed_certificate.cc b/pki/parsed_certificate.cc
index 3e9058d..9e23d30 100644
--- a/pki/parsed_certificate.cc
+++ b/pki/parsed_certificate.cc
@@ -4,7 +4,9 @@
 
 #include "parsed_certificate.h"
 
+#include <openssl/bytestring.h>
 #include <openssl/pool.h>
+
 #include "cert_errors.h"
 #include "certificate_policies.h"
 #include "extended_key_usage.h"
@@ -51,7 +53,7 @@
 
 [[nodiscard]] bool GetSequenceValue(der::Input tlv, der::Input *value) {
   der::Parser parser(tlv);
-  return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
+  return parser.ReadTag(CBS_ASN1_SEQUENCE, value) && !parser.HasMore();
 }
 
 }  // namespace
diff --git a/pki/parser.cc b/pki/parser.cc
index f352178..51f2661 100644
--- a/pki/parser.cc
+++ b/pki/parser.cc
@@ -13,11 +13,11 @@
 
 Parser::Parser(Input input) { CBS_init(&cbs_, input.data(), input.size()); }
 
-bool Parser::PeekTagAndValue(Tag *tag, Input *out) {
+bool Parser::PeekTagAndValue(CBS_ASN1_TAG *tag, Input *out) {
   CBS peeker = cbs_;
   CBS tmp_out;
   size_t header_len;
-  unsigned tag_value;
+  CBS_ASN1_TAG tag_value;
   if (!CBS_get_any_asn1_element(&peeker, &tmp_out, &tag_value, &header_len) ||
       !CBS_skip(&tmp_out, header_len)) {
     return false;
@@ -48,7 +48,7 @@
   return true;
 }
 
-bool Parser::ReadTagAndValue(Tag *tag, Input *out) {
+bool Parser::ReadTagAndValue(CBS_ASN1_TAG *tag, Input *out) {
   if (!PeekTagAndValue(tag, out)) {
     return false;
   }
@@ -56,12 +56,12 @@
   return true;
 }
 
-bool Parser::ReadOptionalTag(Tag tag, std::optional<Input> *out) {
+bool Parser::ReadOptionalTag(CBS_ASN1_TAG tag, std::optional<Input> *out) {
   if (!HasMore()) {
     *out = std::nullopt;
     return true;
   }
-  Tag actual_tag;
+  CBS_ASN1_TAG actual_tag;
   Input value;
   if (!PeekTagAndValue(&actual_tag, &value)) {
     return false;
@@ -76,7 +76,7 @@
   return true;
 }
 
-bool Parser::ReadOptionalTag(Tag tag, Input *out, bool *present) {
+bool Parser::ReadOptionalTag(CBS_ASN1_TAG tag, Input *out, bool *present) {
   std::optional<Input> tmp_out;
   if (!ReadOptionalTag(tag, &tmp_out)) {
     return false;
@@ -86,13 +86,13 @@
   return true;
 }
 
-bool Parser::SkipOptionalTag(Tag tag, bool *present) {
+bool Parser::SkipOptionalTag(CBS_ASN1_TAG tag, bool *present) {
   Input out;
   return ReadOptionalTag(tag, &out, present);
 }
 
-bool Parser::ReadTag(Tag tag, Input *out) {
-  Tag actual_tag;
+bool Parser::ReadTag(CBS_ASN1_TAG tag, Input *out) {
+  CBS_ASN1_TAG actual_tag;
   Input value;
   if (!PeekTagAndValue(&actual_tag, &value) || actual_tag != tag) {
     return false;
@@ -102,15 +102,15 @@
   return true;
 }
 
-bool Parser::SkipTag(Tag tag) {
+bool Parser::SkipTag(CBS_ASN1_TAG tag) {
   Input out;
   return ReadTag(tag, &out);
 }
 
 // Type-specific variants of ReadTag
 
-bool Parser::ReadConstructed(Tag tag, Parser *out) {
-  if (!IsConstructed(tag)) {
+bool Parser::ReadConstructed(CBS_ASN1_TAG tag, Parser *out) {
+  if (!(tag & CBS_ASN1_CONSTRUCTED)) {
     return false;
   }
   Input data;
@@ -122,12 +122,12 @@
 }
 
 bool Parser::ReadSequence(Parser *out) {
-  return ReadConstructed(kSequence, out);
+  return ReadConstructed(CBS_ASN1_SEQUENCE, out);
 }
 
 bool Parser::ReadUint8(uint8_t *out) {
   Input encoded_int;
-  if (!ReadTag(kInteger, &encoded_int)) {
+  if (!ReadTag(CBS_ASN1_INTEGER, &encoded_int)) {
     return false;
   }
   return ParseUint8(encoded_int, out);
@@ -135,7 +135,7 @@
 
 bool Parser::ReadUint64(uint64_t *out) {
   Input encoded_int;
-  if (!ReadTag(kInteger, &encoded_int)) {
+  if (!ReadTag(CBS_ASN1_INTEGER, &encoded_int)) {
     return false;
   }
   return ParseUint64(encoded_int, out);
@@ -143,7 +143,7 @@
 
 std::optional<BitString> Parser::ReadBitString() {
   Input value;
-  if (!ReadTag(kBitString, &value)) {
+  if (!ReadTag(CBS_ASN1_BITSTRING, &value)) {
     return std::nullopt;
   }
   return ParseBitString(value);
@@ -151,7 +151,7 @@
 
 bool Parser::ReadGeneralizedTime(GeneralizedTime *out) {
   Input value;
-  if (!ReadTag(kGeneralizedTime, &value)) {
+  if (!ReadTag(CBS_ASN1_GENERALIZEDTIME, &value)) {
     return false;
   }
   return ParseGeneralizedTime(value, out);
diff --git a/pki/parser.h b/pki/parser.h
index c585c60..64599b5 100644
--- a/pki/parser.h
+++ b/pki/parser.h
@@ -13,7 +13,6 @@
 #include <openssl/bytestring.h>
 
 #include "input.h"
-#include "tag.h"
 
 namespace bssl::der {
 
@@ -106,7 +105,7 @@
   // encoding for the current value is invalid, this method returns false and
   // does not advance the input. Otherwise, it returns true, putting the
   // read tag in |tag| and the value in |out|.
-  [[nodiscard]] bool ReadTagAndValue(Tag *tag, Input *out);
+  [[nodiscard]] bool ReadTagAndValue(CBS_ASN1_TAG *tag, Input *out);
 
   // Reads the current TLV from the input and advances. Unlike ReadTagAndValue
   // where only the value is put in |out|, this puts the raw bytes from the
@@ -123,7 +122,7 @@
   // something else, then |out| is set to nullopt and the input is not
   // advanced. Like ReadTagAndValue, it returns false if the encoding is
   // invalid and does not advance the input.
-  [[nodiscard]] bool ReadOptionalTag(Tag tag, std::optional<Input> *out);
+  [[nodiscard]] bool ReadOptionalTag(CBS_ASN1_TAG tag, std::optional<Input> *out);
 
   // If the current tag in the input is |tag|, it puts the corresponding value
   // in |out|, sets |was_present| to true, and advances the input to the next
@@ -132,25 +131,25 @@
   // false if the encoding is invalid and does not advance the input.
   // DEPRECATED: use the std::optional version above in new code.
   // TODO(mattm): convert the existing callers and remove this override.
-  [[nodiscard]] bool ReadOptionalTag(Tag tag, Input *out, bool *was_present);
+  [[nodiscard]] bool ReadOptionalTag(CBS_ASN1_TAG tag, Input *out, bool *was_present);
 
   // Like ReadOptionalTag, but the value is discarded.
-  [[nodiscard]] bool SkipOptionalTag(Tag tag, bool *was_present);
+  [[nodiscard]] bool SkipOptionalTag(CBS_ASN1_TAG tag, bool *was_present);
 
   // If the current tag matches |tag|, it puts the current value in |out|,
   // advances the input, and returns true. Otherwise, it returns false.
-  [[nodiscard]] bool ReadTag(Tag tag, Input *out);
+  [[nodiscard]] bool ReadTag(CBS_ASN1_TAG tag, Input *out);
 
   // Advances the input and returns true if the current tag matches |tag|;
   // otherwise it returns false.
-  [[nodiscard]] bool SkipTag(Tag tag);
+  [[nodiscard]] bool SkipTag(CBS_ASN1_TAG tag);
 
   // Convenience methods to combine parsing the TLV with parsing the DER
   // encoding for a specific type.
 
   // Reads the current TLV from the input, checks that the tag matches |tag|
   // and is a constructed tag, and creates a new Parser from the value.
-  [[nodiscard]] bool ReadConstructed(Tag tag, Parser *out);
+  [[nodiscard]] bool ReadConstructed(CBS_ASN1_TAG tag, Parser *out);
 
   // A more specific form of ReadConstructed that expects the current tag
   // to be 0x30 (SEQUENCE).
@@ -196,7 +195,7 @@
   // Reads the current TLV from the input, putting the tag in |tag| and the raw
   // value in |out|, but does not advance the input. Returns true if the tag
   // and length are successfully read and the output exists.
-  [[nodiscard]] bool PeekTagAndValue(Tag *tag, Input *out);
+  [[nodiscard]] bool PeekTagAndValue(CBS_ASN1_TAG *tag, Input *out);
 
   // Advances the input to the next TLV. This method only needs to be called
   // after PeekTagAndValue; all other methods will advance the input if they
diff --git a/pki/parser_unittest.cc b/pki/parser_unittest.cc
index e813bfd..2deb1cd 100644
--- a/pki/parser_unittest.cc
+++ b/pki/parser_unittest.cc
@@ -13,10 +13,10 @@
 TEST(ParserTest, ConsumesAllBytesOfTLV) {
   const uint8_t der[] = {0x04 /* OCTET STRING */, 0x00};
   Parser parser((Input(der)));
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  ASSERT_EQ(kOctetString, tag);
+  ASSERT_EQ(CBS_ASN1_OCTETSTRING, tag);
   ASSERT_FALSE(parser.HasMore());
 }
 
@@ -38,7 +38,7 @@
   // with an invalid encoding - its length is too long.
   const uint8_t der[] = {0x30, 0x02, 0x30, 0x7e};
   Parser parser((Input(der)));
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
 }
@@ -58,7 +58,7 @@
   ASSERT_FALSE(parser.HasMore());
 
   // Try to read the INTEGER from the SEQUENCE, which should fail.
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(inner_sequence.ReadTagAndValue(&tag, &value));
 }
@@ -72,14 +72,14 @@
 
   Input value;
   bool present;
-  ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present));
+  ASSERT_TRUE(parser.ReadOptionalTag(CBS_ASN1_INTEGER, &value, &present));
   ASSERT_TRUE(present);
   const uint8_t expected_int_value[] = {0x01};
   ASSERT_EQ(Input(expected_int_value), value);
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  ASSERT_EQ(kOctetString, tag);
+  ASSERT_EQ(CBS_ASN1_OCTETSTRING, tag);
   const uint8_t expected_octet_string_value[] = {0x02};
   ASSERT_EQ(Input(expected_octet_string_value), value);
 
@@ -94,15 +94,15 @@
   Parser parser((Input(der)));
 
   std::optional<Input> optional_value;
-  ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &optional_value));
+  ASSERT_TRUE(parser.ReadOptionalTag(CBS_ASN1_INTEGER, &optional_value));
   ASSERT_TRUE(optional_value.has_value());
   const uint8_t expected_int_value[] = {0x01};
   ASSERT_EQ(Input(expected_int_value), *optional_value);
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  ASSERT_EQ(kOctetString, tag);
+  ASSERT_EQ(CBS_ASN1_OCTETSTRING, tag);
   const uint8_t expected_octet_string_value[] = {0x02};
   ASSERT_EQ(Input(expected_octet_string_value), value);
 
@@ -117,12 +117,12 @@
 
   Input value;
   bool present;
-  ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present));
+  ASSERT_TRUE(parser.ReadOptionalTag(CBS_ASN1_INTEGER, &value, &present));
   ASSERT_FALSE(present);
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  ASSERT_EQ(kOctetString, tag);
+  ASSERT_EQ(CBS_ASN1_OCTETSTRING, tag);
   const uint8_t expected_octet_string_value[] = {0x02};
   ASSERT_EQ(Input(expected_octet_string_value), value);
 
@@ -136,13 +136,13 @@
   Parser parser((Input(der)));
 
   std::optional<Input> optional_value;
-  ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &optional_value));
+  ASSERT_TRUE(parser.ReadOptionalTag(CBS_ASN1_INTEGER, &optional_value));
   ASSERT_FALSE(optional_value.has_value());
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  ASSERT_EQ(kOctetString, tag);
+  ASSERT_EQ(CBS_ASN1_OCTETSTRING, tag);
   const uint8_t expected_octet_string_value[] = {0x02};
   ASSERT_EQ(Input(expected_octet_string_value), value);
 
@@ -153,11 +153,11 @@
   const uint8_t der[] = {0x02 /* INTEGER */, 0x01, 0x01};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
   bool present;
-  ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present));
+  ASSERT_TRUE(parser.ReadOptionalTag(CBS_ASN1_INTEGER, &value, &present));
   ASSERT_FALSE(present);
   ASSERT_FALSE(parser.HasMore());
 }
@@ -167,9 +167,9 @@
   Parser parser((Input(der)));
 
   bool present;
-  ASSERT_TRUE(parser.SkipOptionalTag(kOctetString, &present));
+  ASSERT_TRUE(parser.SkipOptionalTag(CBS_ASN1_OCTETSTRING, &present));
   ASSERT_FALSE(present);
-  ASSERT_TRUE(parser.SkipOptionalTag(kInteger, &present));
+  ASSERT_TRUE(parser.SkipOptionalTag(CBS_ASN1_INTEGER, &present));
   ASSERT_TRUE(present);
   ASSERT_FALSE(parser.HasMore());
 }
@@ -179,10 +179,10 @@
   const uint8_t der[] = {0x9f, 0x1f, 0x00};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-  EXPECT_EQ(kTagContextSpecific | 31u, tag);
+  EXPECT_EQ(CBS_ASN1_CONTEXT_SPECIFIC | 31u, tag);
   ASSERT_FALSE(parser.HasMore());
 }
 
@@ -192,10 +192,10 @@
     const uint8_t der[] = {0x04, 0x00};
     Parser parser((Input(der)));
 
-    Tag tag;
+    CBS_ASN1_TAG tag;
     Input value;
     ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-    EXPECT_EQ(kOctetString, tag);
+    EXPECT_EQ(CBS_ASN1_OCTETSTRING, tag);
   }
 
   {
@@ -203,10 +203,10 @@
     const uint8_t der[] = {0x30, 0x00};
     Parser parser((Input(der)));
 
-    Tag tag;
+    CBS_ASN1_TAG tag;
     Input value;
     ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-    EXPECT_EQ(kSequence, tag);
+    EXPECT_EQ(CBS_ASN1_SEQUENCE, tag);
   }
 
   {
@@ -214,10 +214,10 @@
     const uint8_t der[] = {0x41, 0x00};
     Parser parser((Input(der)));
 
-    Tag tag;
+    CBS_ASN1_TAG tag;
     Input value;
     ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-    EXPECT_EQ(kTagApplication | 1, tag);
+    EXPECT_EQ(CBS_ASN1_APPLICATION | 1, tag);
   }
 
   {
@@ -225,10 +225,10 @@
     const uint8_t der[] = {0xbe, 0x00};
     Parser parser((Input(der)));
 
-    Tag tag;
+    CBS_ASN1_TAG tag;
     Input value;
     ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-    EXPECT_EQ(kTagContextSpecific | kTagConstructed | 30, tag);
+    EXPECT_EQ(CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 30, tag);
   }
 
   {
@@ -236,10 +236,10 @@
     const uint8_t der[] = {0xcf, 0x00};
     Parser parser((Input(der)));
 
-    Tag tag;
+    CBS_ASN1_TAG tag;
     Input value;
     ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value));
-    EXPECT_EQ(kTagPrivate | 15, tag);
+    EXPECT_EQ(CBS_ASN1_PRIVATE | 15, tag);
   }
 }
 
@@ -247,7 +247,7 @@
   const uint8_t der[] = {0x01};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value));
   ASSERT_TRUE(parser.HasMore());
@@ -259,7 +259,7 @@
   const uint8_t der[] = {0x04, 0x81};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value));
   ASSERT_TRUE(parser.HasMore());
@@ -270,7 +270,7 @@
   const uint8_t der[] = {0x04, 0x02, 0x84};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value));
   ASSERT_TRUE(parser.HasMore());
@@ -280,7 +280,7 @@
   const uint8_t der[] = {0x01, 0x81, 0x01, 0x00};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value));
   ASSERT_TRUE(parser.HasMore());
@@ -304,7 +304,7 @@
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
   Parser parser((Input(der)));
 
-  Tag tag;
+  CBS_ASN1_TAG tag;
   Input value;
   ASSERT_FALSE(parser.ReadTagAndValue(&tag, &value));
   ASSERT_TRUE(parser.HasMore());
@@ -315,7 +315,7 @@
   const uint8_t der[] = {0x10, 0x00};
   Parser parser((Input(der)));
 
-  Tag expected_tag = 0x10;
+  CBS_ASN1_TAG expected_tag = 0x10;
   Parser sequence_parser;
   ASSERT_FALSE(parser.ReadConstructed(expected_tag, &sequence_parser));
 
diff --git a/pki/path_builder.cc b/pki/path_builder.cc
index 4bb5d2f..a7fddd3 100644
--- a/pki/path_builder.cc
+++ b/pki/path_builder.cc
@@ -11,6 +11,7 @@
 
 #include <openssl/base.h>
 #include <openssl/sha.h>
+
 #include "cert_issuer_source.h"
 #include "certificate_policies.h"
 #include "common_cert_errors.h"
@@ -18,7 +19,6 @@
 #include "parse_name.h"  // For CertDebugString.
 #include "parser.h"
 #include "string_util.h"
-#include "tag.h"
 #include "trust_store.h"
 #include "verify_certificate_chain.h"
 #include "verify_name_match.h"
diff --git a/pki/signature_algorithm.cc b/pki/signature_algorithm.cc
index 8116862..73d8bc1 100644
--- a/pki/signature_algorithm.cc
+++ b/pki/signature_algorithm.cc
@@ -6,6 +6,7 @@
 
 #include <openssl/bytestring.h>
 #include <openssl/digest.h>
+
 #include "input.h"
 #include "parse_values.h"
 #include "parser.h"
@@ -126,7 +127,7 @@
 [[nodiscard]] bool IsNull(der::Input input) {
   der::Parser parser(input);
   der::Input null_value;
-  if (!parser.ReadTag(der::kNull, &null_value)) {
+  if (!parser.ReadTag(CBS_ASN1_NULL, &null_value)) {
     return false;
   }
 
@@ -237,12 +238,15 @@
   DigestAlgorithm hash, mgf1_hash;
   der::Parser salt_length_parser;
   uint64_t salt_length;
-  if (!params_parser.ReadTag(der::ContextSpecificConstructed(0), &field) ||
+  if (!params_parser.ReadTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &field) ||
       !ParseHashAlgorithm(field, &hash) ||
-      !params_parser.ReadTag(der::ContextSpecificConstructed(1), &field) ||
+      !params_parser.ReadTag(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, &field) ||
       !ParseMaskGenAlgorithm(field, &mgf1_hash) ||
-      !params_parser.ReadConstructed(der::ContextSpecificConstructed(2),
-                                     &salt_length_parser) ||
+      !params_parser.ReadConstructed(
+          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2,
+          &salt_length_parser) ||
       !salt_length_parser.ReadUint64(&salt_length) ||
       salt_length_parser.HasMore() || params_parser.HasMore()) {
     return std::nullopt;
@@ -285,7 +289,7 @@
     return false;
   }
 
-  if (!algorithm_identifier_parser.ReadTag(der::kOid, algorithm)) {
+  if (!algorithm_identifier_parser.ReadTag(CBS_ASN1_OBJECT, algorithm)) {
     return false;
   }
 
diff --git a/pki/tag.cc b/pki/tag.cc
deleted file mode 100644
index d2192ef..0000000
--- a/pki/tag.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tag.h"
-
-#include <openssl/base.h>
-
-namespace bssl::der {
-
-Tag ContextSpecificConstructed(uint8_t tag_number) {
-  BSSL_CHECK(tag_number == (tag_number & kTagNumberMask));
-  return (tag_number & kTagNumberMask) | kTagConstructed | kTagContextSpecific;
-}
-
-Tag ContextSpecificPrimitive(uint8_t base) {
-  BSSL_CHECK(base == (base & kTagNumberMask));
-  return (base & kTagNumberMask) | kTagPrimitive | kTagContextSpecific;
-}
-
-bool IsConstructed(Tag tag) {
-  return (tag & kTagConstructionMask) == kTagConstructed;
-}
-
-}  // namespace bssl::der
diff --git a/pki/tag.h b/pki/tag.h
deleted file mode 100644
index 683e527..0000000
--- a/pki/tag.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BSSL_DER_TAG_H_
-#define BSSL_DER_TAG_H_
-
-#include <stdint.h>
-
-#include <openssl/base.h>
-#include <openssl/bytestring.h>
-
-namespace bssl::der {
-
-// This Tag type represents the identifier for an ASN.1 tag as encoded with
-// DER. It matches the BoringSSL CBS and CBB in-memory representation for a
-// tag.
-//
-// Callers must not assume it matches the DER representation for small tag
-// numbers. Instead, constants are provided for universal class types, and
-// functions are provided for building context specific tags. Tags can also be
-// built from the provided constants and bitmasks.
-using Tag = unsigned;
-
-// Universal class primitive types
-const Tag kBool = CBS_ASN1_BOOLEAN;
-const Tag kInteger = CBS_ASN1_INTEGER;
-const Tag kBitString = CBS_ASN1_BITSTRING;
-const Tag kOctetString = CBS_ASN1_OCTETSTRING;
-const Tag kNull = CBS_ASN1_NULL;
-const Tag kOid = CBS_ASN1_OBJECT;
-const Tag kEnumerated = CBS_ASN1_ENUMERATED;
-const Tag kUtf8String = CBS_ASN1_UTF8STRING;
-const Tag kPrintableString = CBS_ASN1_PRINTABLESTRING;
-const Tag kTeletexString = CBS_ASN1_T61STRING;
-const Tag kIA5String = CBS_ASN1_IA5STRING;
-const Tag kUtcTime = CBS_ASN1_UTCTIME;
-const Tag kGeneralizedTime = CBS_ASN1_GENERALIZEDTIME;
-const Tag kVisibleString = CBS_ASN1_VISIBLESTRING;
-const Tag kUniversalString = CBS_ASN1_UNIVERSALSTRING;
-const Tag kBmpString = CBS_ASN1_BMPSTRING;
-
-// Universal class constructed types
-const Tag kSequence = CBS_ASN1_SEQUENCE;
-const Tag kSet = CBS_ASN1_SET;
-
-// Primitive/constructed bits
-const unsigned kTagPrimitive = 0x00;
-const unsigned kTagConstructed = CBS_ASN1_CONSTRUCTED;
-
-// Tag classes
-const unsigned kTagUniversal = 0x00;
-const unsigned kTagApplication = CBS_ASN1_APPLICATION;
-const unsigned kTagContextSpecific = CBS_ASN1_CONTEXT_SPECIFIC;
-const unsigned kTagPrivate = CBS_ASN1_PRIVATE;
-
-// Masks for the 3 components of a tag (class, primitive/constructed, number)
-const unsigned kTagNumberMask = CBS_ASN1_TAG_NUMBER_MASK;
-const unsigned kTagConstructionMask = CBS_ASN1_CONSTRUCTED;
-const unsigned kTagClassMask = CBS_ASN1_CLASS_MASK;
-
-// Creates the value for the outer tag of an explicitly tagged type.
-//
-// The ASN.1 keyword for this is:
-//     [tag_number] EXPLICIT
-//
-// (Note, the EXPLICIT may be omitted if the entire schema is in
-// EXPLICIT mode, the default)
-OPENSSL_EXPORT Tag ContextSpecificConstructed(uint8_t tag_number);
-
-OPENSSL_EXPORT Tag ContextSpecificPrimitive(uint8_t base);
-
-OPENSSL_EXPORT bool IsConstructed(Tag tag);
-
-}  // namespace bssl::der
-
-#endif  // BSSL_DER_TAG_H_
diff --git a/pki/test_helpers.cc b/pki/test_helpers.cc
index cc32622..b6712af 100644
--- a/pki/test_helpers.cc
+++ b/pki/test_helpers.cc
@@ -147,7 +147,7 @@
 der::Input SequenceValueFromString(std::string_view s) {
   der::Parser parser((der::Input(s)));
   der::Input data;
-  if (!parser.ReadTag(der::kSequence, &data)) {
+  if (!parser.ReadTag(CBS_ASN1_SEQUENCE, &data)) {
     ADD_FAILURE();
     return der::Input();
   }
diff --git a/pki/verify_name_match.cc b/pki/verify_name_match.cc
index 73d3f9a..09f6102 100644
--- a/pki/verify_name_match.cc
+++ b/pki/verify_name_match.cc
@@ -6,12 +6,12 @@
 
 #include <openssl/base.h>
 #include <openssl/bytestring.h>
+
 #include "cert_error_params.h"
 #include "cert_errors.h"
 #include "input.h"
 #include "parse_name.h"
 #include "parser.h"
-#include "tag.h"
 
 namespace bssl {
 
@@ -127,15 +127,15 @@
 
   bool success = false;
   switch (attribute.value_tag) {
-    case der::kPrintableString:
+    case CBS_ASN1_PRINTABLESTRING:
       success = NormalizeDirectoryString(ENFORCE_PRINTABLE_STRING, output);
       break;
-    case der::kBmpString:
-    case der::kUniversalString:
-    case der::kUtf8String:
+    case CBS_ASN1_BMPSTRING:
+    case CBS_ASN1_UNIVERSALSTRING:
+    case CBS_ASN1_UTF8STRING:
       success = NormalizeDirectoryString(NO_ENFORCEMENT, output);
       break;
-    case der::kIA5String:
+    case CBS_ASN1_IA5STRING:
       success = NormalizeDirectoryString(ENFORCE_ASCII, output);
       break;
     default:
@@ -153,15 +153,15 @@
 }
 
 // Returns true if |tag| is a string type that NormalizeValue can handle.
-bool IsNormalizableDirectoryString(der::Tag tag) {
+bool IsNormalizableDirectoryString(CBS_ASN1_TAG tag) {
   switch (tag) {
-    case der::kPrintableString:
-    case der::kUtf8String:
+    case CBS_ASN1_PRINTABLESTRING:
+    case CBS_ASN1_UTF8STRING:
     // RFC 5280 only requires handling IA5String for comparing domainComponent
     // values, but handling it here avoids the need to special case anything.
-    case der::kIA5String:
-    case der::kUniversalString:
-    case der::kBmpString:
+    case CBS_ASN1_IA5STRING:
+    case CBS_ASN1_UNIVERSALSTRING:
+    case CBS_ASN1_BMPSTRING:
       return true;
     // TeletexString isn't normalized. Section 8 of RFC 5280 briefly
     // describes the historical confusion between treating TeletexString
@@ -274,8 +274,8 @@
   der::Parser a_rdn_sequence_counter(a);
   der::Parser b_rdn_sequence_counter(b);
   while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) {
-    if (!a_rdn_sequence_counter.SkipTag(der::kSet) ||
-        !b_rdn_sequence_counter.SkipTag(der::kSet)) {
+    if (!a_rdn_sequence_counter.SkipTag(CBS_ASN1_SET) ||
+        !b_rdn_sequence_counter.SkipTag(CBS_ASN1_SET)) {
       return false;
     }
   }
@@ -294,8 +294,8 @@
   der::Parser b_rdn_sequence(b);
   while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) {
     der::Parser a_rdn, b_rdn;
-    if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) ||
-        !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) {
+    if (!a_rdn_sequence.ReadConstructed(CBS_ASN1_SET, &a_rdn) ||
+        !b_rdn_sequence.ReadConstructed(CBS_ASN1_SET, &b_rdn)) {
       return false;
     }
     if (!VerifyRdnMatch(&a_rdn, &b_rdn)) {
@@ -324,7 +324,7 @@
   while (rdn_sequence_parser.HasMore()) {
     // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
     der::Parser rdn_parser;
-    if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) {
+    if (!rdn_sequence_parser.ReadConstructed(CBS_ASN1_SET, &rdn_parser)) {
       return false;
     }
     RelativeDistinguishedName type_and_values;
@@ -412,7 +412,7 @@
   der::Parser rdn_sequence_parser(name_rdn_sequence);
   while (rdn_sequence_parser.HasMore()) {
     der::Parser rdn_parser;
-    if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) {
+    if (!rdn_sequence_parser.ReadConstructed(CBS_ASN1_SET, &rdn_parser)) {
       return false;
     }
 
diff --git a/sources.cmake b/sources.cmake
index 0ea805b..d32f24b 100644
--- a/sources.cmake
+++ b/sources.cmake
@@ -382,7 +382,6 @@
   pki/signature_algorithm.cc
   pki/simple_path_builder_delegate.cc
   pki/string_util.cc
-  pki/tag.cc
   pki/trust_store_collection.cc
   pki/trust_store_in_memory.cc
   pki/trust_store.cc