blob: 7afb27e25c03691c432af1bedfeae807bc1903cd [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_
#define NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_
#include <map>
#include <memory>
#include <vector>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/cert/internal/certificate_policies.h"
#include "net/cert/internal/parse_certificate.h"
#include "net/der/input.h"
#include "third_party/boringssl/src/include/openssl/base.h"
namespace net {
struct GeneralNames;
class NameConstraints;
class ParsedCertificate;
class SignatureAlgorithm;
class CertErrors;
using ParsedCertificateList = std::vector<scoped_refptr<ParsedCertificate>>;
// Represents an X.509 certificate, including Certificate, TBSCertificate, and
// standard extensions.
// Creating a ParsedCertificate does not completely parse and validate the
// certificate data. Presence of a member in this class implies the DER was
// parsed successfully to that level, but does not imply the contents of that
// member are valid, unless otherwise specified. See the documentation for each
// member or the documentation of the type it returns.
class NET_EXPORT ParsedCertificate
: public base::RefCountedThreadSafe<ParsedCertificate> {
public:
// Map from OID to ParsedExtension.
using ExtensionsMap = std::map<der::Input, ParsedExtension>;
// Creates a ParsedCertificate given a DER-encoded Certificate. Returns
// nullptr on failure. Failure will occur if the standard certificate fields
// and supported extensions cannot be parsed.
// On either success or failure, if |errors| is non-null it may have error
// information added to it.
static scoped_refptr<ParsedCertificate> Create(
bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
const ParseCertificateOptions& options,
CertErrors* errors);
// Creates a ParsedCertificate by copying the provided |data|, and appends it
// to |chain|. Returns true if the certificate was successfully parsed and
// added. If false is return, |chain| is unmodified.
//
// On either success or failure, if |errors| is non-null it may have error
// information added to it.
static bool CreateAndAddToVector(
bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
const ParseCertificateOptions& options,
std::vector<scoped_refptr<net::ParsedCertificate>>* chain,
CertErrors* errors);
// Like Create() this builds a ParsedCertificate given a DER-encoded
// Certificate and returns nullptr on failure.
//
// However a copy of |data| is NOT made.
//
// This is a dangerous way to create as ParsedCertificate and should only be
// used with care when saving a copy is really worth it, or the data is known
// to come from static storage (and hence remain valid for entire life of
// process).
//
// ParsedCertificate is reference counted, so it is easy to extend the life
// and and end up with a ParsedCertificate referencing feed memory.
//
// On either success or failure, if |errors| is non-null it may have error
// information added to it.
static scoped_refptr<ParsedCertificate> CreateWithoutCopyingUnsafe(
const uint8_t* data,
size_t length,
const ParseCertificateOptions& options,
CertErrors* errors);
// Returns the DER-encoded certificate data for this cert.
const der::Input& der_cert() const { return cert_; }
// Accessors for raw fields of the Certificate.
const der::Input& tbs_certificate_tlv() const { return tbs_certificate_tlv_; }
const der::Input& signature_algorithm_tlv() const {
return signature_algorithm_tlv_;
}
const der::BitString& signature_value() const { return signature_value_; }
// Accessor for struct containing raw fields of the TbsCertificate.
const ParsedTbsCertificate& tbs() const { return tbs_; }
// Returns the signatureAlgorithm of the Certificate (not the tbsCertificate).
const SignatureAlgorithm& signature_algorithm() const {
DCHECK(signature_algorithm_);
return *signature_algorithm_;
}
// Returns the DER-encoded normalized subject value (not including outer
// Sequence tag). This is gauranteed to be valid DER, though the contents of
// unhandled string types are treated as raw bytes.
der::Input normalized_subject() const {
return der::Input(&normalized_subject_);
}
// Returns the DER-encoded normalized issuer value (not including outer
// Sequence tag). This is gauranteed to be valid DER, though the contents of
// unhandled string types are treated as raw bytes.
der::Input normalized_issuer() const {
return der::Input(&normalized_issuer_);
}
// Returns true if the certificate has a BasicConstraints extension.
bool has_basic_constraints() const { return has_basic_constraints_; }
// Returns the ParsedBasicConstraints struct. Caller must check
// has_basic_constraints() before accessing this.
const ParsedBasicConstraints& basic_constraints() const {
DCHECK(has_basic_constraints_);
return basic_constraints_;
}
// Returns true if the certificate has a KeyUsage extension.
bool has_key_usage() const { return has_key_usage_; }
// Returns the KeyUsage BitString. Caller must check
// has_key_usage() before accessing this.
const der::BitString& key_usage() const {
DCHECK(has_key_usage_);
return key_usage_;
}
// Returns true if the certificate has a ExtendedKeyUsage extension.
bool has_extended_key_usage() const { return has_extended_key_usage_; }
// Returns the ExtendedKeyUsage key purpose OIDs. Caller must check
// has_extended_key_usage() before accessing this.
const std::vector<der::Input>& extended_key_usage() const {
DCHECK(has_extended_key_usage_);
return extended_key_usage_;
}
// Returns true if the certificate has a SubjectAltName extension.
bool has_subject_alt_names() const { return subject_alt_names_ != nullptr; }
// Returns the ParsedExtension struct for the SubjectAltName extension.
// If the cert did not have a SubjectAltName extension, this will be a
// default-initialized ParsedExtension struct.
const ParsedExtension& subject_alt_names_extension() const {
return subject_alt_names_extension_;
}
// Returns the GeneralNames class parsed from SubjectAltName extension, or
// nullptr if no SubjectAltName extension was present.
const GeneralNames* subject_alt_names() const {
return subject_alt_names_.get();
}
// Returns true if the certificate has a NameConstraints extension.
bool has_name_constraints() const { return name_constraints_ != nullptr; }
// Returns the parsed NameConstraints extension. Must not be called if
// has_name_constraints() is false.
const NameConstraints& name_constraints() const {
DCHECK(name_constraints_);
return *name_constraints_;
}
// Returns true if the certificate has an AuthorityInfoAccess extension.
bool has_authority_info_access() const { return has_authority_info_access_; }
// Returns the ParsedExtension struct for the AuthorityInfoAccess extension.
const ParsedExtension& authority_info_access_extension() const {
return authority_info_access_extension_;
}
// Returns any caIssuers URIs from the AuthorityInfoAccess extension.
const std::vector<base::StringPiece>& ca_issuers_uris() const {
return ca_issuers_uris_;
}
// Returns any OCSP URIs from the AuthorityInfoAccess extension.
const std::vector<base::StringPiece>& ocsp_uris() const { return ocsp_uris_; }
// Returns true if the certificate has a Policies extension.
bool has_policy_oids() const { return has_policy_oids_; }
// Returns the policy OIDs. Caller must check has_policy_oids() before
// accessing this.
const std::vector<der::Input>& policy_oids() const {
DCHECK(has_policy_oids());
return policy_oids_;
}
// Returns true if the certificate has a PolicyConstraints extension.
bool has_policy_constraints() const { return has_policy_constraints_; }
// Returns the ParsedPolicyConstraints struct. Caller must check
// has_policy_constraints() before accessing this.
const ParsedPolicyConstraints& policy_constraints() const {
DCHECK(has_policy_constraints_);
return policy_constraints_;
}
// Returns true if the certificate has a PolicyMappings extension.
bool has_policy_mappings() const { return has_policy_mappings_; }
// Returns the PolicyMappings extension. Caller must check
// has_policy_mappings() before accessing this.
const std::vector<ParsedPolicyMapping>& policy_mappings() const {
DCHECK(has_policy_mappings_);
return policy_mappings_;
}
// Returns true if the certificate has a InhibitAnyPolicy extension.
bool has_inhibit_any_policy() const { return has_inhibit_any_policy_; }
// Returns the Inhibit Any Policy extension. Caller must check
// has_inhibit_any_policy() before accessing this.
uint8_t inhibit_any_policy() const {
DCHECK(has_inhibit_any_policy_);
return inhibit_any_policy_;
}
// Returns a map of all the extensions in the certificate.
const ExtensionsMap& extensions() const { return extensions_; }
// Gets the value for extension matching |extension_oid|. Returns false if the
// extension is not present.
bool GetExtension(const der::Input& extension_oid,
ParsedExtension* parsed_extension) const;
private:
friend class base::RefCountedThreadSafe<ParsedCertificate>;
ParsedCertificate();
~ParsedCertificate();
// Creates a ParsedCertificate. If |backing_data| is non-null, the
// certificate's DER-encoded data will be referenced from here. Otherwise the
// certificate's data will be |static_data|, and the pointer MUST remain
// valid and its data unmodified for the entirety of the program.
static scoped_refptr<ParsedCertificate> CreateInternal(
bssl::UniquePtr<CRYPTO_BUFFER> backing_data,
der::Input static_data,
const ParseCertificateOptions& options,
CertErrors* errors);
// The backing store for the certificate data. May be null if created by
// CreateWithoutCopyingUnsafe.
bssl::UniquePtr<CRYPTO_BUFFER> cert_data_;
// Points to the raw certificate DER.
der::Input cert_;
der::Input tbs_certificate_tlv_;
der::Input signature_algorithm_tlv_;
der::BitString signature_value_;
ParsedTbsCertificate tbs_;
// The signatureAlgorithm from the Certificate.
std::unique_ptr<SignatureAlgorithm> signature_algorithm_;
// Normalized DER-encoded Subject (not including outer Sequence tag).
std::string normalized_subject_;
// Normalized DER-encoded Issuer (not including outer Sequence tag).
std::string normalized_issuer_;
// BasicConstraints extension.
bool has_basic_constraints_ = false;
ParsedBasicConstraints basic_constraints_;
// KeyUsage extension.
bool has_key_usage_ = false;
der::BitString key_usage_;
// ExtendedKeyUsage extension.
bool has_extended_key_usage_ = false;
std::vector<der::Input> extended_key_usage_;
// Raw SubjectAltName extension.
ParsedExtension subject_alt_names_extension_;
// Parsed SubjectAltName extension.
std::unique_ptr<GeneralNames> subject_alt_names_;
// NameConstraints extension.
std::unique_ptr<NameConstraints> name_constraints_;
// AuthorityInfoAccess extension.
bool has_authority_info_access_ = false;
ParsedExtension authority_info_access_extension_;
// CaIssuers and Ocsp URIs parsed from the AuthorityInfoAccess extension. Note
// that the AuthorityInfoAccess may have contained other AccessDescriptions
// which are not represented here.
std::vector<base::StringPiece> ca_issuers_uris_;
std::vector<base::StringPiece> ocsp_uris_;
// Policies extension.
bool has_policy_oids_ = false;
std::vector<der::Input> policy_oids_;
// Policy constraints extension.
bool has_policy_constraints_ = false;
ParsedPolicyConstraints policy_constraints_;
// Policy mappings extension.
bool has_policy_mappings_ = false;
std::vector<ParsedPolicyMapping> policy_mappings_;
// Inhibit Any Policy extension.
bool has_inhibit_any_policy_ = false;
uint8_t inhibit_any_policy_;
// All of the extensions.
ExtensionsMap extensions_;
DISALLOW_COPY_AND_ASSIGN(ParsedCertificate);
};
} // namespace net
#endif // NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_