// Copyright (c) 2011 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_BASE_X509_CERTIFICATE_H_ #define NET_BASE_X509_CERTIFICATE_H_ #pragma once #include <string.h> #include <string> #include <vector> #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/string_piece.h" #include "base/time.h" #include "net/base/net_export.h" #include "net/base/x509_cert_types.h" #if defined(OS_WIN) #include <windows.h> #include <wincrypt.h> #elif defined(OS_MACOSX) #include <CoreFoundation/CFArray.h> #include <Security/SecBase.h> #include "base/synchronization/lock.h" #elif defined(USE_OPENSSL) // Forward declaration; real one in <x509.h> struct x509_st; typedef struct x509_store_st X509_STORE; #elif defined(USE_NSS) // Forward declaration; real one in <cert.h> struct CERTCertificateStr; #endif class Pickle; namespace crypto { class StringPiece; class RSAPrivateKey; } // namespace crypto namespace net { class CertVerifyResult; typedef std::vector<scoped_refptr<X509Certificate> > CertificateList; // X509Certificate represents an X.509 certificate used by SSL. class NET_EXPORT X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { public: // A handle to the certificate object in the underlying crypto library. // We assume that OSCertHandle is a pointer type on all platforms and // NULL is an invalid OSCertHandle. #if defined(OS_WIN) typedef PCCERT_CONTEXT OSCertHandle; #elif defined(OS_MACOSX) typedef SecCertificateRef OSCertHandle; #elif defined(USE_OPENSSL) typedef struct x509_st* OSCertHandle; #elif defined(USE_NSS) typedef struct CERTCertificateStr* OSCertHandle; #else // TODO(ericroman): not implemented typedef void* OSCertHandle; #endif typedef std::vector<OSCertHandle> OSCertHandles; // Predicate functor used in maps when X509Certificate is used as the key. class LessThan { public: bool operator() (X509Certificate* lhs, X509Certificate* rhs) const; }; // Where the certificate comes from. The enumeration constants are // listed in increasing order of preference. enum Source { SOURCE_UNUSED = 0, // The source_ member is not used. SOURCE_LONE_CERT_IMPORT = 1, // From importing a certificate without // any intermediate CA certificates. SOURCE_FROM_CACHE = 2, // From the disk cache - which contains // intermediate CA certificates, but may be // stale. SOURCE_FROM_NETWORK = 3, // From the network. }; enum VerifyFlags { VERIFY_REV_CHECKING_ENABLED = 1 << 0, VERIFY_EV_CERT = 1 << 1, }; enum Format { // The data contains a single DER-encoded certificate, or a PEM-encoded // DER certificate with the PEM encoding block name of "CERTIFICATE". // Any subsequent blocks will be ignored. FORMAT_SINGLE_CERTIFICATE = 1 << 0, // The data contains a sequence of one or more PEM-encoded, DER // certificates, with the PEM encoding block name of "CERTIFICATE". // All PEM blocks will be parsed, until the first error is encountered. FORMAT_PEM_CERT_SEQUENCE = 1 << 1, // The data contains a PKCS#7 SignedData structure, whose certificates // member is to be used to initialize the certificate and intermediates. // The data may further be encoded using PEM, specifying block names of // either "PKCS7" or "CERTIFICATE". FORMAT_PKCS7 = 1 << 2, // Automatically detect the format. FORMAT_AUTO = FORMAT_SINGLE_CERTIFICATE | FORMAT_PEM_CERT_SEQUENCE | FORMAT_PKCS7, }; enum PickleType { // When reading a certificate from a Pickle, the Pickle only contains a // single certificate. PICKLETYPE_SINGLE_CERTIFICATE, // When reading a certificate from a Pickle, the Pickle contains the // the certificate plus any certificates that were stored in // |intermediate_ca_certificates_| at the time it was serialized. PICKLETYPE_CERTIFICATE_CHAIN, }; // Creates a X509Certificate from the ground up. Used by tests that simulate // SSL connections. X509Certificate(const std::string& subject, const std::string& issuer, base::Time start_date, base::Time expiration_date); // Create an X509Certificate from a handle to the certificate object in the // underlying crypto library. |source| specifies where |cert_handle| comes // from. Given two certificate handles for the same certificate, our // certificate cache prefers the handle from the network because our HTTP // cache isn't caching the corresponding intermediate CA certificates yet // (http://crbug.com/7065). // The returned pointer must be stored in a scoped_refptr<X509Certificate>. static scoped_refptr<X509Certificate> CreateFromHandle(OSCertHandle cert_handle, Source source, const OSCertHandles& intermediates); // Create an X509Certificate from a chain of DER encoded certificates. The // first certificate in the chain is the end-entity certificate to which a // handle is returned. The other certificates in the chain are intermediate // certificates. See the comment for |CreateFromHandle| about the |source| // argument. // The returned pointer must be stored in a scoped_refptr<X509Certificate>. static scoped_refptr<X509Certificate> CreateFromDERCertChain( const std::vector<base::StringPiece>& der_certs); // Create an X509Certificate from the DER-encoded representation. // Returns NULL on failure. // // The returned pointer must be stored in a scoped_refptr<X509Certificate>. static scoped_refptr<X509Certificate> CreateFromBytes(const char* data, int length); // Create an X509Certificate from the representation stored in the given // pickle. The data for this object is found relative to the given // pickle_iter, which should be passed to the pickle's various Read* methods. // Returns NULL on failure. // // The returned pointer must be stored in a scoped_refptr<X509Certificate>. static scoped_refptr<X509Certificate> CreateFromPickle(const Pickle& pickle, void** pickle_iter, PickleType type); // Parses all of the certificates possible from |data|. |format| is a // bit-wise OR of Format, indicating the possible formats the // certificates may have been serialized as. If an error occurs, an empty // collection will be returned. static CertificateList CreateCertificateListFromBytes(const char* data, int length, int format); // Create a self-signed certificate containing the public key in |key|. // Subject, serial number and validity period are given as parameters. // The certificate is signed by the private key in |key|. The hashing // algorithm for the signature is SHA-1. // // |subject| is a distinguished name defined in RFC4514. // // An example: // CN=Michael Wong,O=FooBar Corporation,DC=foobar,DC=com // // SECURITY WARNING // // Using self-signed certificates has the following security risks: // 1. Encryption without authentication and thus vulnerable to // man-in-the-middle attacks. // 2. Self-signed certificates cannot be revoked. // // Use this certificate only after the above risks are acknowledged. static scoped_refptr<X509Certificate> CreateSelfSigned(crypto::RSAPrivateKey* key, const std::string& subject, uint32 serial_number, base::TimeDelta valid_duration); // Appends a representation of this object to the given pickle. void Persist(Pickle* pickle); // The subject of the certificate. For HTTPS server certificates, this // represents the web server. The common name of the subject should match // the host name of the web server. const CertPrincipal& subject() const { return subject_; } // The issuer of the certificate. const CertPrincipal& issuer() const { return issuer_; } // Time period during which the certificate is valid. More precisely, this // certificate is invalid before the |valid_start| date and invalid after // the |valid_expiry| date. // If we were unable to parse either date from the certificate (or if the cert // lacks either date), the date will be null (i.e., is_null() will be true). const base::Time& valid_start() const { return valid_start_; } const base::Time& valid_expiry() const { return valid_expiry_; } // The fingerprint of this certificate. const SHA1Fingerprint& fingerprint() const { return fingerprint_; } // Gets the DNS names in the certificate. Pursuant to RFC 2818, Section 3.1 // Server Identity, if the certificate has a subjectAltName extension of // type dNSName, this method gets the DNS names in that extension. // Otherwise, it gets the common name in the subject field. void GetDNSNames(std::vector<std::string>* dns_names) const; // Convenience method that returns whether this certificate has expired as of // now. bool HasExpired() const; // Returns true if this object and |other| represent the same certificate. bool Equals(const X509Certificate* other) const; // Returns intermediate certificates added via AddIntermediateCertificate(). // Ownership follows the "get" rule: it is the caller's responsibility to // retain the elements of the result. const OSCertHandles& GetIntermediateCertificates() const { return intermediate_ca_certs_; } // Returns true if I already contain the given intermediate cert. bool HasIntermediateCertificate(OSCertHandle cert); // Returns true if I already contain all the given intermediate certs. bool HasIntermediateCertificates(const OSCertHandles& certs); #if defined(OS_MACOSX) // Does this certificate's usage allow SSL client authentication? bool SupportsSSLClientAuth() const; // Do any of the given issuer names appear in this cert's chain of trust? bool IsIssuedBy(const std::vector<CertPrincipal>& valid_issuers); // Creates a security policy for SSL client certificates. static OSStatus CreateSSLClientPolicy(SecPolicyRef* outPolicy); // Adds all available SSL client identity certs to the given vector. // |server_domain| is a hint for which domain the cert is to be sent to // (a cert previously specified as the default for that domain will be given // precedence and returned first in the output vector.) // If valid_issuers is non-empty, only certs that were transitively issued by // one of the given names will be included in the list. static bool GetSSLClientCertificates( const std::string& server_domain, const std::vector<CertPrincipal>& valid_issuers, CertificateList* certs); // Creates the chain of certs to use for this client identity cert. CFArrayRef CreateClientCertificateChain() const; #endif #if defined(OS_WIN) // Returns a handle to a global, in-memory certificate store. We use it for // two purposes: // 1. Import server certificates into this store so that we can verify and // display the certificates using CryptoAPI. // 2. Copy client certificates from the "MY" system certificate store into // this store so that we can close the system store when we finish // searching for client certificates. static HCERTSTORE cert_store(); #endif #if defined(USE_OPENSSL) // Returns a handle to a global, in-memory certificate store. We // use it for test code, e.g. importing the test server's certificate. static X509_STORE* cert_store(); #endif #if defined(ANDROID) // Returns the certificate chain in DER-encoded form, using the application DER // cache as appropriate. void GetChainDEREncodedBytes(std::vector<std::string>* chain_bytes) const; #endif // Verifies the certificate against the given hostname. Returns OK if // successful or an error code upon failure. // // The |*verify_result| structure, including the |verify_result->cert_status| // bitmask, is always filled out regardless of the return value. If the // certificate has multiple errors, the corresponding status flags are set in // |verify_result->cert_status|, and the error code for the most serious // error is returned. // // |flags| is bitwise OR'd of VerifyFlags. // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, certificate revocation // checking is performed. If VERIFY_EV_CERT is set in |flags| too, // EV certificate verification is performed. int Verify(const std::string& hostname, int flags, CertVerifyResult* verify_result) const; // Verifies that |hostname| matches this certificate. // Does not verify that the certificate is valid, only that the certificate // matches this host. // Returns true if it matches. // // WARNING: This function may return false negatives (for example, if // |hostname| is an IP address literal) on some platforms. Only // use in cases where some false-positives are acceptible. bool VerifyNameMatch(const std::string& hostname) const; // This method returns the DER encoded certificate. // If the return value is true then the DER encoded certificate is available. // The content of the DER encoded certificate is written to |encoded|. bool GetDEREncoded(std::string* encoded); OSCertHandle os_cert_handle() const { return cert_handle_; } // Returns true if two OSCertHandles refer to identical certificates. static bool IsSameOSCert(OSCertHandle a, OSCertHandle b); // Creates an OS certificate handle from the BER-encoded representation. // Returns NULL on failure. static OSCertHandle CreateOSCertHandleFromBytes(const char* data, int length); // Creates all possible OS certificate handles from |data| encoded in a // specific |format|. Returns an empty collection on failure. static OSCertHandles CreateOSCertHandlesFromBytes( const char* data, int length, Format format); // Duplicates (or adds a reference to) an OS certificate handle. static OSCertHandle DupOSCertHandle(OSCertHandle cert_handle); // Frees (or releases a reference to) an OS certificate handle. static void FreeOSCertHandle(OSCertHandle cert_handle); private: friend class base::RefCountedThreadSafe<X509Certificate>; friend class TestRootCerts; // For unit tests FRIEND_TEST_ALL_PREFIXES(X509CertificateTest, Cache); FRIEND_TEST_ALL_PREFIXES(X509CertificateTest, IntermediateCertificates); FRIEND_TEST_ALL_PREFIXES(X509CertificateTest, SerialNumbers); FRIEND_TEST_ALL_PREFIXES(X509CertificateNameVerifyTest, VerifyHostname); // Construct an X509Certificate from a handle to the certificate object // in the underlying crypto library. X509Certificate(OSCertHandle cert_handle, Source source, const OSCertHandles& intermediates); ~X509Certificate(); // Common object initialization code. Called by the constructors only. void Initialize(); #if defined(OS_WIN) bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context, const char* policy_oid) const; static bool IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context); #endif #if defined(OS_MACOSX) static bool IsIssuedByKnownRoot(CFArrayRef chain); #endif bool VerifyEV() const; #if defined(USE_OPENSSL) // Resets the store returned by cert_store() to default state. Used by // TestRootCerts to undo modifications. static void ResetCertStore(); #endif // Calculates the SHA-1 fingerprint of the certificate. Returns an empty // (all zero) fingerprint on failure. static SHA1Fingerprint CalculateFingerprint(OSCertHandle cert_handle); // Verifies that |hostname| matches one of the names in |cert_names|, based on // TLS name matching rules, specifically following http://tools.ietf.org/html/draft-saintandre-tls-server-id-check-09#section-4.4.3 // The members of |cert_names| must have been extracted from the Subject CN or // SAN fields of a certificate. // WARNING: This function may return false negatives (for example, if // |hostname| is an IP address literal) on some platforms. Only // use in cases where some false-positives are acceptible. static bool VerifyHostname(const std::string& hostname, const std::vector<std::string>& cert_names); // The serial number, DER encoded. // NOTE: keep this method private, used by IsBlacklisted only. To simplify // IsBlacklisted, we strip the leading 0 byte of a serial number, used to // encode a positive DER INTEGER (a signed type) with a most significant bit // of 1. Other code must not use this method for general purpose until this // is fixed. const std::string& serial_number() const { return serial_number_; } // IsBlacklisted returns true if this certificate is explicitly blacklisted. bool IsBlacklisted() const; // IsPublicKeyBlacklisted returns true iff one of |public_key_hashes| (which // are SHA1 hashes of SubjectPublicKeyInfo structures) is explicitly blocked. static bool IsPublicKeyBlacklisted( const std::vector<SHA1Fingerprint>& public_key_hashes); // IsSHA1HashInSortedArray returns true iff |hash| is in |array|, a sorted // array of SHA1 hashes. static bool IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, const uint8* array, size_t array_byte_len); // Reads a single certificate from |pickle| and returns a platform-specific // certificate handle. The format of the certificate stored in |pickle| is // not guaranteed to be the same across different underlying cryptographic // libraries, nor acceptable to CreateFromBytes(). Returns an invalid // handle, NULL, on failure. static OSCertHandle ReadCertHandleFromPickle(const Pickle& pickle, void** pickle_iter); // Writes a single certificate to |pickle|. Returns false on failure. static bool WriteCertHandleToPickle(OSCertHandle handle, Pickle* pickle); #ifdef ANDROID #if defined(USE_OPENSSL) // Returns the certificate in DER-encoded form, using the application DER // cache as appropriate. The returned string piece will be valid as long // as the handle is. static std::string GetDEREncodedBytes(OSCertHandle handle); #endif #endif // The subject of the certificate. CertPrincipal subject_; // The issuer of the certificate. CertPrincipal issuer_; // This certificate is not valid before |valid_start_| base::Time valid_start_; // This certificate is not valid after |valid_expiry_| base::Time valid_expiry_; // The fingerprint of this certificate. SHA1Fingerprint fingerprint_; // The serial number of this certificate, DER encoded. std::string serial_number_; // A handle to the certificate object in the underlying crypto library. OSCertHandle cert_handle_; // Untrusted intermediate certificates associated with this certificate // that may be needed for chain building. OSCertHandles intermediate_ca_certs_; #if defined(OS_MACOSX) // Blocks multiple threads from verifying the cert simultaneously. // (Marked mutable because it's used in a const method.) mutable base::Lock verification_lock_; #endif // Where the certificate comes from. Source source_; DISALLOW_COPY_AND_ASSIGN(X509Certificate); }; } // namespace net #endif // NET_BASE_X509_CERTIFICATE_H_