Replace hardcoded parameters

This commit is contained in:
Lu Chen
2020-01-27 16:05:15 -08:00
parent cdd4d97e0f
commit 5c42bf9b7f
134 changed files with 9510 additions and 1938 deletions

View File

@@ -16,9 +16,11 @@
#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "common/ec_key.h"
#include "common/error_space.h"
#include "common/rsa_key.h"
#include "common/sha_util.h"
#include "common/signer_public_key.h"
#include "protos/public/drm_certificate.pb.h"
#include "protos/public/errors.pb.h"
#include "protos/public/signed_drm_certificate.pb.h"
@@ -33,6 +35,13 @@ const char kTestingString[] = "test"; // Code development / unit tests.
const bool kUseCache = true;
// Restrict the certificate chain size. All leaf DRM certificates must be a
// DEVICE certificate. The DEVICE certificate must be signed by a MODEL
// certificate. The MODEL certificate can be signed by Widevine or by a
// PROVISIONER certificate which is signed by Widevine. Do not allow any
// additional links.
const uint32_t kMaxCertificateChainSize = 3;
// From common::TestDrmCertificates.
// TODO(user): common::test_certificates is a testonly target, consider
// how to use instead of dupliciating the test cert here.
@@ -248,12 +257,17 @@ static const unsigned char kProdRootCertificate[] = {
// number (signer).
struct VerifiedCertSignature {
VerifiedCertSignature(const std::string& cert, const std::string& sig,
const std::string& signer_sn)
: signed_cert(cert), signature(sig), signer_serial(signer_sn) {}
const std::string& signer_sn,
const std::string& signer_pub_key)
: signed_cert(cert),
signature(sig),
signer_serial(signer_sn),
signer_public_key(signer_pub_key) {}
std::string signed_cert;
std::string signature;
std::string signer_serial;
std::string signer_public_key;
};
// Map of certificate serial number to its signature.
@@ -265,50 +279,57 @@ class VerifiedCertSignatureCache {
// Checks cache, on miss, uses public key. If successful, adds to
// cache.
Status VerifySignature(const std::string& cert, const std::string& serial_number,
Status VerifySignature(const std::string& cert,
const std::string& serial_number,
const std::string& signature,
const std::string& signer_public_key,
const std::string& signer_serial_number) {
const DrmCertificate& signer) {
{
VerifiedCertSignatures::iterator cached_signature;
absl::ReaderMutexLock read_lock(&signature_cache_mutex_);
cached_signature = signature_cache_.find(serial_number);
if (cached_signature != signature_cache_.end()) {
// TODO(user): Log which of the following three conditions occurs.
if ((cert != cached_signature->second.signed_cert) ||
(signature != cached_signature->second.signature) ||
(signer_serial_number != cached_signature->second.signer_serial)) {
// Cached signature mismatch.
if (cert != cached_signature->second.signed_cert) {
return Status(error_space, INVALID_SIGNATURE, "cached-cert-mismatch");
}
if (signature != cached_signature->second.signature) {
return Status(error_space, INVALID_SIGNATURE,
"cached-signature-mismatch");
}
// Cached signature match.
if (signer.serial_number() != cached_signature->second.signer_serial) {
return Status(error_space, INVALID_SIGNATURE,
"cached-serial-number-mismatch");
}
if (signer.public_key() != cached_signature->second.signer_public_key) {
return Status(error_space, INVALID_SIGNATURE,
"cached-signer-public-key-mismatch");
}
return OkStatus();
}
}
// Cache miss. Verify signature.
std::unique_ptr<RsaPublicKey> signer_key(
key_factory_->CreateFromPkcs1PublicKey(signer_public_key));
if (!signer_key) {
std::unique_ptr<SignerPublicKey> signer_public_key =
SignerPublicKey::Create(signer.public_key(), signer.algorithm());
if (signer_public_key == nullptr) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"invalid-signer-public-key");
}
if (!signer_key->VerifySignature(cert, signature)) {
if (!signer_public_key->VerifySignature(cert, signature)) {
return Status(error_space, INVALID_SIGNATURE,
"cache-miss-invalid-signature");
}
// Add signature to cache.
absl::WriterMutexLock write_lock(&signature_cache_mutex_);
signature_cache_.emplace(
serial_number,
VerifiedCertSignature(cert, signature, signer_serial_number));
VerifiedCertSignature(cert, signature, signer.serial_number(),
signer.public_key()));
return OkStatus();
}
private:
VerifiedCertSignatures signature_cache_ GUARDED_BY(&signature_cache_mutex_);
VerifiedCertSignatures signature_cache_
ABSL_GUARDED_BY(&signature_cache_mutex_);
absl::Mutex signature_cache_mutex_;
const RsaKeyFactory* key_factory_;
};
@@ -330,7 +351,8 @@ std::unique_ptr<DrmRootCertificate> DrmRootCertificate::CreateByType(
}
Status DrmRootCertificate::CreateByTypeString(
const std::string& cert_type_string, std::unique_ptr<DrmRootCertificate>* cert) {
const std::string& cert_type_string,
std::unique_ptr<DrmRootCertificate>* cert) {
CHECK(cert);
CertificateType cert_type;
@@ -400,9 +422,9 @@ Status DrmRootCertificate::Create(CertificateType cert_type,
"missing-root-certificate-signature");
}
std::unique_ptr<RsaPublicKey> public_key(
key_factory->CreateFromPkcs1PublicKey(root_cert.public_key()));
if (!public_key) {
std::unique_ptr<SignerPublicKey> public_key =
SignerPublicKey::Create(root_cert.public_key(), root_cert.algorithm());
if (public_key == nullptr) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"invalid-root-public-key");
}
@@ -424,10 +446,11 @@ DrmRootCertificate::DrmRootCertificate(
std::unique_ptr<RsaKeyFactory> key_factory)
: type_(type),
serialized_certificate_(serialized_certificate),
serial_number_(serial_number),
public_key_(public_key),
key_factory_(std::move(key_factory)),
signature_cache_(new VerifiedCertSignatureCache(key_factory_.get())) {}
signature_cache_(new VerifiedCertSignatureCache(key_factory_.get())) {
root_cert_.set_public_key(public_key);
root_cert_.set_serial_number(serial_number);
}
DrmRootCertificate::~DrmRootCertificate() {}
@@ -472,8 +495,9 @@ Status DrmRootCertificate::VerifyCertificate(
}
// Verify signature chain, but do not use cache for leaf certificates.
uint32_t certs_in_chain = 0;
return VerifySignatures(*signed_certificate, certificate->serial_number(),
!kUseCache);
!kUseCache, &certs_in_chain);
}
// Recursively verifies certificates with their signing certs or the root.
@@ -483,39 +507,48 @@ Status DrmRootCertificate::VerifyCertificate(
// Signatures for root-signed certificates are always cached, even if they are
// leaf certificates. For example service, and provisioner certificates.
Status DrmRootCertificate::VerifySignatures(
const SignedDrmCertificate& signed_cert, const std::string& cert_serial_number,
bool use_cache) const {
const SignedDrmCertificate& signed_cert,
const std::string& cert_serial_number, bool use_cache,
uint32_t* certs_in_chain) const {
CHECK(certs_in_chain);
if (++(*certs_in_chain) > kMaxCertificateChainSize) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"certificate-chain-size-exceeded");
}
if (!signed_cert.has_signer()) {
// Always use cache for root-signed certificates.
return signature_cache_->VerifySignature(
signed_cert.drm_certificate(), cert_serial_number,
signed_cert.signature(), public_key(), serial_number_);
signed_cert.signature(), root_cert_);
}
DrmCertificate signer;
if (!signer.ParseFromString(signed_cert.signer().drm_certificate())) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"invalid-signer-certificate");
}
// Signer cannot be a device certificate.
if (signer.type() == DrmCertificate::DEVICE) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"device-cert-must-be-leaf");
}
// Verify the signer before verifying signed_cert.
Status status =
VerifySignatures(signed_cert.signer(), signer.serial_number(), kUseCache);
Status status = VerifySignatures(signed_cert.signer(), signer.serial_number(),
kUseCache, certs_in_chain);
if (!status.ok()) {
return status;
}
if (use_cache) {
status = signature_cache_->VerifySignature(
signed_cert.drm_certificate(), cert_serial_number,
signed_cert.signature(), signer.public_key(), signer.serial_number());
status = signature_cache_->VerifySignature(signed_cert.drm_certificate(),
cert_serial_number,
signed_cert.signature(), signer);
if (!status.ok()) {
return status;
}
} else {
std::unique_ptr<RsaPublicKey> signer_public_key(
key_factory_->CreateFromPkcs1PublicKey(signer.public_key()));
if (!signer_public_key) {
std::unique_ptr<SignerPublicKey> signer_public_key =
SignerPublicKey::Create(signer.public_key(), signer.algorithm());
if (signer_public_key == nullptr) {
return Status(error_space, INVALID_DRM_CERTIFICATE,
"invalid-leaf-signer-public-key");
}