Files
media_cas_packager_sdk_source/common/x509_cert.h
Fang Yu bc68878bdf Minimal implementation of Widevine MediaCAS ECMG.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=226515998
2018-12-21 14:25:01 -08:00

177 lines
6.0 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Copyright 2017 Google LLC.
//
// This software is licensed under the terms defined in the Widevine Master
// License Agreement. For a copy of this agreement, please contact
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
//
// Description:
// X.509 certificate classes used by the license server SDK.
#ifndef COMMON_X509_CERT_H_
#define COMMON_X509_CERT_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
#include "openssl/pem.h"
#include "openssl/x509.h"
#include "openssl/x509v3.h"
#include "common/openssl_util.h"
#include "common/rsa_key.h"
#include "common/status.h"
namespace widevine {
// NOTE: All Status codes are in the canonical error space.
// Class which holds a single X.509 certificates.
class X509Cert {
public:
// Load the certificate from an openssl X509 certificate instance.
static std::unique_ptr<X509Cert> FromOpenSslCert(ScopedX509 openssl_cert_);
X509Cert();
virtual ~X509Cert();
// Load an X.509 certificate. Takes a single parameter, |pem_cert|, which is
// a PEM-encoded certificate.
Status LoadPem(const std::string& pem_cert);
// Load an X.509 certificate. Takes a single parameter, |pem_cert|, which is
// a DER-encoded certificate.
Status LoadDer(const std::string& der_cert);
// Return a std::string containing the PEM-encoded certificate.
std::string GetPem() const;
// Returns certificate RSA public key. nullptr if not found, or if key type
// is not RSA.
std::unique_ptr<RsaPublicKey> GetRsaPublicKey() const;
// Returns the internal OpenSSL X509 certificate.
const X509* openssl_cert() const { return openssl_cert_; }
// Returns the certificate subject name.
const std::string& GetSubjectName();
// Returns a field within the certificate subject name, or an empty std::string
// if the field is not found.
std::string GetSubjectNameField(const std::string& field);
// Returns the certificate serial number, binary encoded, or an empty std::string
// if an error occurs.
std::string GetSerialNumber() const;
// Gets the start of the validity period for the certificate in seconds
// since the epoch. |valid_start_seconds| must not be null. Returns true on
// success, false otherwise.
bool GetNotBeforeSeconds(int64_t* valid_start_seconds) const;
// Gets the end of the validity period for the certificate in seconds
// since the epoch. |valid_end_seconds| must not be null. Returns true on
// success, false otherwise.
bool GetNotAfterSeconds(int64_t* valid_end_seconds) const;
// Returns true if the certificate is a CA (root or intermediate) certificate.
bool IsCaCertificate() const;
// Gets the value of an X.509 V3 extension encoded as a boolean. |oid| is the
// object identifier sequence for the extension, and |value| is a pointer to
// an integer which will contain the extension value upon successful return.
// Returns true if successful, or false otherwise.
bool GetV3BooleanExtension(const std::string& oid, bool* value) const;
private:
explicit X509Cert(X509* openssl_cert);
Status Asn1TimeToEpochSeconds(const ASN1_TIME* asn1_time,
int64_t* epoch_seconds) const;
X509* openssl_cert_;
std::string subject_name_;
friend class X509CertChain;
DISALLOW_COPY_AND_ASSIGN(X509Cert);
};
// Class which holds a chain of X.509 certificates.
class X509CertChain {
public:
X509CertChain() {}
virtual ~X509CertChain();
// Loads a chain of PEM-encoded X.509 certificates. Takes a single parameter,
// |pem_cert_chain|, which is the concatenation of a number of PEM X.509
// certificates, beginning with the leaf certificate, and ending with the
// certificate signed by the root CA.
Status LoadPem(const std::string& pem_cert_chain);
// Loads a chain of DER-encoded PKCS#7 certificates. Takes a single parameter,
// |pk7_cert_chain|, which is a DER-encoded PKCS#7 X.509 certificate
// container.
Status LoadPkcs7(const std::string& pk7_cert_chain);
// Writes the |cert_chain_| to a DER-encoded PKCS#7 X.509 cryptographic
// message. The final message does not include signed data.
std::string GetPkcs7();
// Returns the number of certificates in the chain.
size_t GetNumCerts() const { return cert_chain_.size(); }
// Returns the X509Cert at the specified chain index (0 start). Returns
// NULL if cert_index is out of range. The X509CertChain retains ownwership
// of the object returned.
X509Cert* GetCert(size_t cert_index) const;
private:
void Reset();
std::vector<X509Cert*> cert_chain_;
DISALLOW_COPY_AND_ASSIGN(X509CertChain);
};
// CA class which holds the root CA cert, and verifies certificate chains.
class X509CA {
public:
// New object assumes ownership of |ca_cert|.
explicit X509CA(X509Cert* ca_cert);
virtual ~X509CA();
// Does X.509 PKI validation of |cert| against the root CA certificate
// used when constructing X509CA. This method is thread-safe.
Status VerifyCert(const X509Cert& cert);
// Does X.509 PKI validation of |cert_chain| against the root CA certificate
// used when constructing X509CA. This method is thread-safe.
Status VerifyCertChain(const X509CertChain& cert_chain);
// Does X.509 PKI validation of |cert| using the |cert_chain|
// certificates. This method allows |cert| to be an ICA. This method is
// thread-safe.
Status VerifyCertWithChain(const X509Cert& cert,
const X509CertChain& cert_chain);
private:
Status InitializeStore();
Status OpenSslX509Verify(const X509* cert, STACK_OF(X509) * intermediates);
std::unique_ptr<X509Cert> ca_cert_;
absl::Mutex openssl_store_mutex_;
X509_STORE* openssl_store_ GUARDED_BY(openssl_store_mutex_);
DISALLOW_IMPLICIT_CONSTRUCTORS(X509CA);
};
} // namespace widevine
#endif // COMMON_X509_CERT_H_