// 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 "verify_name_match.h"

#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 {

DEFINE_CERT_ERROR_ID(kFailedConvertingAttributeValue,
                     "Failed converting AttributeValue to string");
DEFINE_CERT_ERROR_ID(kFailedNormalizingString, "Failed normalizing string");

namespace {

// Types of character set checking that NormalizeDirectoryString can perform.
enum CharsetEnforcement {
  NO_ENFORCEMENT,
  ENFORCE_PRINTABLE_STRING,
  ENFORCE_ASCII,
};

// Normalizes |output|, a UTF-8 encoded string, as if it contained
// only ASCII characters.
//
// This could be considered a partial subset of RFC 5280 rules, and
// is compatible with RFC 2459/3280.
//
// In particular, RFC 5280, Section 7.1 describes how UTF8String
// and PrintableString should be compared - using the LDAP StringPrep
// profile of RFC 4518, with case folding and whitespace compression.
// However, because it is optional for 2459/3280 implementations and because
// it's desirable to avoid the size cost of the StringPrep tables,
// this function treats |output| as if it was composed of ASCII.
//
// That is, rather than folding all whitespace characters, it only
// folds ' '. Rather than case folding using locale-aware handling,
// it only folds A-Z to a-z.
//
// This gives better results than outright rejecting (due to mismatched
// encodings), or from doing a strict binary comparison (the minimum
// required by RFC 3280), and is sufficient for those certificates
// publicly deployed.
//
// If |charset_enforcement| is not NO_ENFORCEMENT and |output| contains any
// characters not allowed in the specified charset, returns false.
//
// NOTE: |output| will be modified regardless of the return.
[[nodiscard]] bool NormalizeDirectoryString(
    CharsetEnforcement charset_enforcement, std::string *output) {
  // Normalized version will always be equal or shorter than input.
  // Normalize in place and then truncate the output if necessary.
  std::string::const_iterator read_iter = output->begin();
  std::string::iterator write_iter = output->begin();

  for (; read_iter != output->end() && *read_iter == ' '; ++read_iter) {
    // Ignore leading whitespace.
  }

  for (; read_iter != output->end(); ++read_iter) {
    const unsigned char c = *read_iter;
    if (c == ' ') {
      // If there are non-whitespace characters remaining in input, compress
      // multiple whitespace chars to a single space, otherwise ignore trailing
      // whitespace.
      std::string::const_iterator next_iter = read_iter + 1;
      if (next_iter != output->end() && *next_iter != ' ') {
        *(write_iter++) = ' ';
      }
    } else if (c >= 'A' && c <= 'Z') {
      // Fold case.
      *(write_iter++) = c + ('a' - 'A');
    } else {
      // Note that these checks depend on the characters allowed by earlier
      // conditions also being valid for the enforced charset.
      switch (charset_enforcement) {
        case ENFORCE_PRINTABLE_STRING:
          // See NormalizePrintableStringValue comment for the acceptable list
          // of characters.
          if (!((c >= 'a' && c <= 'z') || (c >= '\'' && c <= ':') || c == '=' ||
                c == '?')) {
            return false;
          }
          break;
        case ENFORCE_ASCII:
          if (c > 0x7F) {
            return false;
          }
          break;
        case NO_ENFORCEMENT:
          break;
      }
      *(write_iter++) = c;
    }
  }
  if (write_iter != output->end()) {
    output->erase(write_iter, output->end());
  }
  return true;
}

// Converts the value of X509NameAttribute |attribute| to UTF-8, normalizes it,
// and stores in |output|. The type of |attribute| must be one of the types for
// which IsNormalizableDirectoryString is true.
//
// If the value of |attribute| can be normalized, returns true and sets
// |output| to the case folded, normalized value. If the value of |attribute|
// is invalid, returns false.
// NOTE: |output| will be modified regardless of the return.
[[nodiscard]] bool NormalizeValue(X509NameAttribute attribute,
                                  std::string *output, CertErrors *errors) {
  BSSL_CHECK(errors);

  if (!attribute.ValueAsStringUnsafe(output)) {
    errors->AddError(kFailedConvertingAttributeValue,
                     CreateCertErrorParams1SizeT("tag", attribute.value_tag));
    return false;
  }

  bool success = false;
  switch (attribute.value_tag) {
    case der::kPrintableString:
      success = NormalizeDirectoryString(ENFORCE_PRINTABLE_STRING, output);
      break;
    case der::kBmpString:
    case der::kUniversalString:
    case der::kUtf8String:
      success = NormalizeDirectoryString(NO_ENFORCEMENT, output);
      break;
    case der::kIA5String:
      success = NormalizeDirectoryString(ENFORCE_ASCII, output);
      break;
    default:
      // NOTREACHED
      success = false;
      break;
  }

  if (!success) {
    errors->AddError(kFailedNormalizingString,
                     CreateCertErrorParams1SizeT("tag", attribute.value_tag));
  }

  return success;
}

// Returns true if |tag| is a string type that NormalizeValue can handle.
bool IsNormalizableDirectoryString(der::Tag tag) {
  switch (tag) {
    case der::kPrintableString:
    case der::kUtf8String:
    // 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:
      return true;
    // TeletexString isn't normalized. Section 8 of RFC 5280 briefly
    // describes the historical confusion between treating TeletexString
    // as Latin1String vs T.61, and there are even incompatibilities within
    // T.61 implementations. As this time is virtually unused, simply
    // treat it with a binary comparison, as permitted by RFC 3280/5280.
    default:
      return false;
  }
}

// Returns true if the value of X509NameAttribute |a| matches |b|.
bool VerifyValueMatch(X509NameAttribute a, X509NameAttribute b) {
  if (IsNormalizableDirectoryString(a.value_tag) &&
      IsNormalizableDirectoryString(b.value_tag)) {
    std::string a_normalized, b_normalized;
    // TODO(eroman): Plumb this down.
    CertErrors unused_errors;
    if (!NormalizeValue(a, &a_normalized, &unused_errors) ||
        !NormalizeValue(b, &b_normalized, &unused_errors)) {
      return false;
    }
    return a_normalized == b_normalized;
  }
  // Attributes encoded with different types may be assumed to be unequal.
  if (a.value_tag != b.value_tag) {
    return false;
  }
  // All other types use binary comparison.
  return a.value == b.value;
}

// Verifies that |a_parser| and |b_parser| are the same length and that every
// AttributeTypeAndValue in |a_parser| has a matching AttributeTypeAndValue in
// |b_parser|.
bool VerifyRdnMatch(der::Parser *a_parser, der::Parser *b_parser) {
  RelativeDistinguishedName a_type_and_values, b_type_and_values;
  if (!ReadRdn(a_parser, &a_type_and_values) ||
      !ReadRdn(b_parser, &b_type_and_values)) {
    return false;
  }

  // RFC 5280 section 7.1:
  // Two relative distinguished names RDN1 and RDN2 match if they have the same
  // number of naming attributes and for each naming attribute in RDN1 there is
  // a matching naming attribute in RDN2.
  if (a_type_and_values.size() != b_type_and_values.size()) {
    return false;
  }

  // The ordering of elements may differ due to denormalized values sorting
  // differently in the DER encoding. Since the number of elements should be
  // small, a naive linear search for each element should be fine. (Hostile
  // certificates already have ways to provoke pathological behavior.)
  for (const auto &a : a_type_and_values) {
    auto b_iter = b_type_and_values.begin();
    for (; b_iter != b_type_and_values.end(); ++b_iter) {
      const auto &b = *b_iter;
      if (a.type == b.type && VerifyValueMatch(a, b)) {
        break;
      }
    }
    if (b_iter == b_type_and_values.end()) {
      return false;
    }
    // Remove the matched element from b_type_and_values to ensure duplicate
    // elements in a_type_and_values can't match the same element in
    // b_type_and_values multiple times.
    b_type_and_values.erase(b_iter);
  }

  // Every element in |a_type_and_values| had a matching element in
  // |b_type_and_values|.
  return true;
}

enum NameMatchType {
  EXACT_MATCH,
  SUBTREE_MATCH,
};

// Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if
// they are an exact match as defined by RFC 5280 7.1. If |match_type| is
// SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as
// defined by RFC 5280 7.1.
//
// |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag),
// defined in RFC 5280 section 4.1.2.4:
//
// Name ::= CHOICE { -- only one possibility for now --
//   rdnSequence  RDNSequence }
//
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
//
// RelativeDistinguishedName ::=
//   SET SIZE (1..MAX) OF AttributeTypeAndValue
bool VerifyNameMatchInternal(const der::Input &a, const der::Input &b,
                             NameMatchType match_type) {
  // Empty Names are allowed.  RFC 5280 section 4.1.2.4 requires "The issuer
  // field MUST contain a non-empty distinguished name (DN)", while section
  // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is
  // assumed to have verified those conditions.

  // RFC 5280 section 7.1:
  // Two distinguished names DN1 and DN2 match if they have the same number of
  // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching
  // RDNs appear in the same order in both DNs.

  // As an optimization, first just compare the number of RDNs:
  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)) {
      return false;
    }
  }
  // If doing exact match and either of the sequences has more elements than the
  // other, not a match. If doing a subtree match, the first Name may have more
  // RDNs than the second.
  if (b_rdn_sequence_counter.HasMore()) {
    return false;
  }
  if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore()) {
    return false;
  }

  // Verify that RDNs in |a| and |b| match.
  der::Parser a_rdn_sequence(a);
  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)) {
      return false;
    }
    if (!VerifyRdnMatch(&a_rdn, &b_rdn)) {
      return false;
    }
  }

  return true;
}

}  // namespace

bool NormalizeName(const der::Input &name_rdn_sequence,
                   std::string *normalized_rdn_sequence, CertErrors *errors) {
  BSSL_CHECK(errors);

  // RFC 5280 section 4.1.2.4
  // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
  der::Parser rdn_sequence_parser(name_rdn_sequence);

  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 0)) {
    return false;
  }

  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)) {
      return false;
    }
    RelativeDistinguishedName type_and_values;
    if (!ReadRdn(&rdn_parser, &type_and_values)) {
      return false;
    }

    CBB rdn_cbb;
    if (!CBB_add_asn1(cbb.get(), &rdn_cbb, CBS_ASN1_SET)) {
      return false;
    }

    for (const auto &type_and_value : type_and_values) {
      // AttributeTypeAndValue ::= SEQUENCE {
      //   type     AttributeType,
      //   value    AttributeValue }
      CBB attribute_type_and_value_cbb, type_cbb, value_cbb;
      if (!CBB_add_asn1(&rdn_cbb, &attribute_type_and_value_cbb,
                        CBS_ASN1_SEQUENCE)) {
        return false;
      }

      // AttributeType ::= OBJECT IDENTIFIER
      if (!CBB_add_asn1(&attribute_type_and_value_cbb, &type_cbb,
                        CBS_ASN1_OBJECT) ||
          !CBB_add_bytes(&type_cbb, type_and_value.type.UnsafeData(),
                         type_and_value.type.Length())) {
        return false;
      }

      // AttributeValue ::= ANY -- DEFINED BY AttributeType
      if (IsNormalizableDirectoryString(type_and_value.value_tag)) {
        std::string normalized_value;
        if (!NormalizeValue(type_and_value, &normalized_value, errors)) {
          return false;
        }
        if (!CBB_add_asn1(&attribute_type_and_value_cbb, &value_cbb,
                          CBS_ASN1_UTF8STRING) ||
            !CBB_add_bytes(
                &value_cbb,
                reinterpret_cast<const uint8_t *>(normalized_value.data()),
                normalized_value.size())) {
          return false;
        }
      } else {
        if (!CBB_add_asn1(&attribute_type_and_value_cbb, &value_cbb,
                          type_and_value.value_tag) ||
            !CBB_add_bytes(&value_cbb, type_and_value.value.UnsafeData(),
                           type_and_value.value.Length())) {
          return false;
        }
      }

      if (!CBB_flush(&rdn_cbb)) {
        return false;
      }
    }

    // Ensure the encoded AttributeTypeAndValue values in the SET OF are sorted.
    if (!CBB_flush_asn1_set_of(&rdn_cbb) || !CBB_flush(cbb.get())) {
      return false;
    }
  }

  normalized_rdn_sequence->assign(CBB_data(cbb.get()),
                                  CBB_data(cbb.get()) + CBB_len(cbb.get()));
  return true;
}

bool VerifyNameMatch(const der::Input &a_rdn_sequence,
                     const der::Input &b_rdn_sequence) {
  return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH);
}

bool VerifyNameInSubtree(const der::Input &name_rdn_sequence,
                         const der::Input &parent_rdn_sequence) {
  return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence,
                                 SUBTREE_MATCH);
}

bool FindEmailAddressesInName(
    const der::Input &name_rdn_sequence,
    std::vector<std::string> *contained_email_addresses) {
  contained_email_addresses->clear();

  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)) {
      return false;
    }

    RelativeDistinguishedName type_and_values;
    if (!ReadRdn(&rdn_parser, &type_and_values)) {
      return false;
    }

    for (const auto &type_and_value : type_and_values) {
      if (type_and_value.type == der::Input(kTypeEmailAddressOid)) {
        std::string email_address;
        if (!type_and_value.ValueAsString(&email_address)) {
          return false;
        }
        contained_email_addresses->push_back(std::move(email_address));
      }
    }
  }

  return true;
}

}  // namespace bssl
