Restructed reference root of trust (3/3 OEM Cert)

[ Merge of http://go/wvgerrit/116944 ]

This change is the last part of a three part change for restructing
the root of trust used by the reference implementation.

OEM Certificates are now managed by the root of trust of the crypto
engine.  Previously, OEM certs where handled separately on a session
by session basis.

Bug: 135283522
Test: oemcrypto_unittests ce_cdm_tests
Change-Id: I6cf1fa3fade28baad85b5fce57a8eab6f2ed17c1
This commit is contained in:
Alex Dale
2021-02-18 20:00:15 -08:00
parent f6f5099604
commit 9f7e2c4413
7 changed files with 120 additions and 72 deletions

View File

@@ -177,9 +177,6 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18,
0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03
};
// Filler for returning vector references.
const std::vector<uint8_t> kEmptyVector;
} // namespace
bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) {
@@ -187,10 +184,12 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) {
// If provisioning method is something other than ProvisioningError
// indicates it has already been initialized before. Must
// existing data.
rsa_key_.reset();
test_rsa_key_.reset();
drm_cert_key_.reset();
test_drm_cert_key_.reset();
keybox_.reset();
test_keybox_.reset();
oem_cert_.reset();
oem_cert_key_.reset();
}
prov_method_ = method;
switch (method) {
@@ -198,7 +197,7 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) {
std::unique_ptr<RsaPrivateKey> key =
RsaPrivateKey::Load(kPrivateKey, kPrivateKeySize);
if (key) {
rsa_key_ = std::move(key);
drm_cert_key_ = std::move(key);
} else {
// This error message is OK in unit tests which use test certificate.
LOGE(
@@ -230,8 +229,7 @@ bool AuthenticationRoot::IsValid() const {
return HasDeviceKey();
}
case OEMCrypto_OEMCertificate: {
// TODO(sigquit): Add OEM Certificate validation.
return true;
return HasOemCertKey() && HasDeviceKey();
}
default: {
LOGE("Root of trust is not properly initialized");
@@ -251,8 +249,11 @@ OEMCryptoResult AuthenticationRoot::IsKeyboxOrOemCertValid() const {
return kb->IsKeyboxValid();
}
case OEMCrypto_OEMCertificate: {
LOGW("OEM certificate validation is not implemented");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
if (!oem_cert_) {
LOGW("OEM cert is not installed");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
return oem_cert_->IsCertificateValid();
}
case OEMCrypto_DrmCertificate: {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
@@ -300,7 +301,7 @@ std::vector<uint8_t> AuthenticationRoot::DeviceId() const {
}
if (prov_method_ == OEMCrypto_Keybox) {
LOGE("Expected keybox to be set for a device ID");
return kEmptyVector;
return std::vector<uint8_t>();
}
return std::vector<uint8_t>(kFakeDeviceId.begin(), kFakeDeviceId.end());
}
@@ -311,7 +312,7 @@ std::vector<uint8_t> AuthenticationRoot::DeviceKey() const {
return kb->DeviceKey();
}
LOGE("No device key has been set");
return kEmptyVector;
return std::vector<uint8_t>();
}
bool AuthenticationRoot::HasDeviceKey() const { return keybox() != nullptr; }
@@ -326,7 +327,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() {
LOGE("System does not support DRM certificates");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (test_rsa_key_) {
if (test_drm_cert_key_) {
LOGE("Test RSA key is already loaded");
return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
}
@@ -337,7 +338,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() {
LOGE("Failed to load test RSA key");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
test_rsa_key_ = std::move(key);
test_drm_cert_key_ = std::move(key);
return OEMCrypto_SUCCESS;
}
@@ -399,22 +400,48 @@ OEMCryptoResult AuthenticationRoot::GetKeyData(uint8_t* key_data,
return kb->GetKeyData(key_data, key_data_length);
}
OEMCryptoResult AuthenticationRoot::InstallOemCertificate(
const uint8_t* private_key, size_t private_key_size,
const uint8_t* public_cert, size_t public_cert_size) {
if (prov_method_ != OEMCrypto_OEMCertificate) {
LOGE("System does not support OEM certificates");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (oem_cert_ || oem_cert_key_) {
LOGE("OEM certificate is already installed");
return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
}
std::unique_ptr<OemCertificate> oem_cert = OemCertificate::Create(
private_key, private_key_size, public_cert, public_cert_size);
if (!oem_cert) {
LOGE("Failed to install OEM certificate as root of trust");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (oem_cert->key_type() != OemCertificate::kRsa) {
LOGE("Only RSA-based OEM certificates supported");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
std::unique_ptr<RsaPrivateKey> oem_cert_key =
RsaPrivateKey::Load(oem_cert->GetPrivateKey());
if (!oem_cert_key) {
LOGE("Failed to parse OEM certificate private key");
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
oem_cert_ = std::move(oem_cert);
oem_cert_key_ = std::move(oem_cert_key);
return OEMCrypto_SUCCESS;
}
OEMCryptoResult AuthenticationRoot::GetOemPublicCertificate(
uint8_t* public_cert, size_t* public_cert_length) const {
if (prov_method_ != OEMCrypto_OEMCertificate) {
LOGE("System does not support OEM certificates");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
LOGE("OEM certificates have not been implemented on auth root");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
const std::vector<uint8_t>& AuthenticationRoot::GetOemPrivateKey() const {
if (prov_method_ != OEMCrypto_OEMCertificate) {
LOGE("System does not support OEM certificates");
return kEmptyVector;
if (!oem_cert_) {
LOGE("OEM certificate is not installed");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
LOGE("OEM certificates have not been implemented on auth root");
return kEmptyVector;
return oem_cert_->GetPublicCertificate(public_cert, public_cert_length);
}
} // namespace wvoec_ref

View File

@@ -15,6 +15,7 @@
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "disallow_copy_and_assign.h"
#include "oemcrypto_keybox_ref.h"
#include "oemcrypto_oem_cert.h"
#include "oemcrypto_rsa_key.h"
namespace wvoec_ref {
@@ -67,12 +68,12 @@ class AuthenticationRoot {
// Returns the shared RSA private key from the built-in DRM
// Certificate.
std::shared_ptr<RsaPrivateKey> ShareDrmCertKey() {
return test_rsa_key_ ? test_rsa_key_ : rsa_key_;
return test_drm_cert_key_ ? test_drm_cert_key_ : drm_cert_key_;
}
RsaPrivateKey* DrmCertKey() const {
return test_rsa_key_ ? test_rsa_key_.get() : rsa_key_.get();
return test_drm_cert_key_ ? test_drm_cert_key_.get() : drm_cert_key_.get();
}
bool HasDrmCertKey() const { return test_rsa_key_ || rsa_key_; }
bool HasDrmCertKey() const { return test_drm_cert_key_ || drm_cert_key_; }
// Loads the system's built-in RSA key. Only implemented for
// devices that are that pre-provisioned with a built-in DRM
@@ -82,7 +83,7 @@ class AuthenticationRoot {
OEMCryptoResult LoadTestRsaKey();
// Removes any installed test RSA key.
void RemoveTestRsaKey() { test_rsa_key_.reset(); }
void RemoveTestRsaKey() { test_drm_cert_key_.reset(); }
// Keybox-based root of trust API.
@@ -124,6 +125,14 @@ class AuthenticationRoot {
// OEM Certificate-base root of trust API.
// Installs an OEM certificate as the root of trust. The provided
// private key and public cert are parsed, but not validated. The
// private key will be made available for sessions to load.
OEMCryptoResult InstallOemCertificate(const uint8_t* private_key,
size_t private_key_size,
const uint8_t* public_cert,
size_t public_cert_size);
// For OEM Cert-based devices, returns the OEM Public Certificate
// component of the OEM Certificate.
// This method implements the expected behavior of
@@ -135,7 +144,9 @@ class AuthenticationRoot {
// the OEM private key into a session.
// Should only be called for devices that use OEM Certificates
// for provisioning.
const std::vector<uint8_t>& GetOemPrivateKey() const;
std::shared_ptr<RsaPrivateKey> ShareOemCertKey() { return oem_cert_key_; }
RsaPrivateKey* OemCertKey() const { return oem_cert_key_.get(); }
bool HasOemCertKey() const { return static_cast<bool>(oem_cert_key_); }
private:
OEMCrypto_ProvisioningMethod prov_method_ = OEMCrypto_ProvisioningError;
@@ -143,13 +154,17 @@ class AuthenticationRoot {
// DRM certificate.
// If no keybox, this is the private key of the baked-in DRM
// Certificate.
std::shared_ptr<RsaPrivateKey> rsa_key_;
std::shared_ptr<RsaPrivateKey> test_rsa_key_;
std::shared_ptr<RsaPrivateKey> drm_cert_key_;
std::shared_ptr<RsaPrivateKey> test_drm_cert_key_;
// Keybox data.
std::unique_ptr<WvKeybox> keybox_;
std::unique_ptr<WvKeybox> test_keybox_;
// OEM certificate.
std::unique_ptr<OemCertificate> oem_cert_;
std::shared_ptr<RsaPrivateKey> oem_cert_key_;
CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot);
};
} // namespace wvoec_ref

View File

@@ -24,6 +24,15 @@ class Prov30CryptoEngine : public CryptoEngine {
explicit Prov30CryptoEngine(std::unique_ptr<wvcdm::FileSystem>&& file_system)
: CryptoEngine(std::move(file_system)) {}
bool Initialize() override {
if (!CryptoEngine::Initialize()) {
return false;
}
const OEMCryptoResult result = InstallOemCertificate(
kOEMPrivateKey, kOEMPrivateKeySize, kOEMPublicCert, kOEMPublicCertSize);
return result == OEMCrypto_SUCCESS;
}
bool config_local_display_only() { return true; }
// Returns the max HDCP version supported.
@@ -47,31 +56,6 @@ class Prov30CryptoEngine : public CryptoEngine {
return OEMCrypto_OEMCertificate;
}
OEMCryptoResult get_oem_certificate(SessionContext* session,
uint8_t* public_cert,
size_t* public_cert_length) {
if (kOEMPublicCertSize == 0) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (public_cert_length == nullptr) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (*public_cert_length < kOEMPublicCertSize) {
*public_cert_length = kOEMPublicCertSize;
return OEMCrypto_ERROR_SHORT_BUFFER;
}
*public_cert_length = kOEMPublicCertSize;
if (public_cert == nullptr) {
return OEMCrypto_ERROR_SHORT_BUFFER;
}
memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize);
if (!session->LoadRsaDrmKey(kOEMPrivateKey, kOEMPrivateKeySize)) {
LOGE("Private RSA Key did not load correctly.");
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
return OEMCrypto_SUCCESS;
}
// Returns "L3" for a software only library. L1 is for hardware protected
// keys and data paths. L2 is for hardware protected keys but no data path
// protection.

View File

@@ -75,8 +75,8 @@ class CryptoEngine {
OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); }
OEMCryptoResult IsKeyboxValid() const {
return root_of_trust_.IsKeyboxValid();
OEMCryptoResult IsKeyboxOrOemCertValid() const {
return root_of_trust_.IsKeyboxOrOemCertValid();
}
std::vector<uint8_t> DeviceRootKey() const {
@@ -97,6 +97,26 @@ class CryptoEngine {
return root_of_trust_.GetKeyData(key_data, key_data_length);
}
OEMCryptoResult InstallOemCertificate(const uint8_t* private_key,
size_t private_key_size,
const uint8_t* public_cert,
size_t public_cert_size) {
return root_of_trust_.InstallOemCertificate(private_key, private_key_size,
public_cert, public_cert_size);
}
OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert,
size_t* public_cert_length) const {
return root_of_trust_.GetOemPublicCertificate(public_cert,
public_cert_length);
}
std::shared_ptr<RsaPrivateKey> ShareOemPrivateKey() {
return root_of_trust_.ShareOemCertKey();
}
bool HasOemPrivateKey() const { return root_of_trust_.HasOemCertKey(); }
virtual void Terminate();
virtual SessionId OpenSession();
@@ -155,15 +175,6 @@ class CryptoEngine {
return OEMCrypto_Keybox;
}
virtual OEMCryptoResult get_oem_certificate(uint8_t* public_cert,
size_t* public_cert_length) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
virtual OEMCryptoResult load_oem_private_key(SessionContext* session) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
// Used for OEMCrypto_IsAntiRollbackHwPresent.
virtual bool config_is_anti_rollback_hw_present() { return false; }

View File

@@ -762,10 +762,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) {
case OEMCrypto_DrmCertificate:
return OEMCrypto_SUCCESS;
case OEMCrypto_Keybox:
return crypto_engine->IsKeyboxValid();
case OEMCrypto_OEMCertificate:
// TODO(sigquit): verify that the certificate exists and is valid.
return OEMCrypto_SUCCESS;
return crypto_engine->IsKeyboxOrOemCertValid();
default:
LOGE("Invalid provisioning method: %d.",
crypto_engine->config_provisioning_method());
@@ -797,7 +795,7 @@ OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) {
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION;
}
return crypto_engine->load_oem_private_key(session_ctx);
return session_ctx->LoadOemPrivateKey();
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
@@ -811,7 +809,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
crypto_engine->config_provisioning_method());
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
return crypto_engine->get_oem_certificate(public_cert, public_cert_length);
return crypto_engine->GetOemPublicCertificate(public_cert,
public_cert_length);
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id,

View File

@@ -296,6 +296,15 @@ OEMCryptoResult SessionContext::RSADeriveKeys(
return DeriveKeys(session_key_, mac_key_context, enc_key_context);
}
OEMCryptoResult SessionContext::LoadOemPrivateKey() {
if (!ce_->HasOemPrivateKey()) {
LOGE("No OEM private key");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
rsa_key_ = ce_->ShareOemPrivateKey();
return OEMCrypto_SUCCESS;
}
OEMCryptoResult SessionContext::PrepAndSignLicenseRequest(
uint8_t* message, size_t message_length, size_t* core_message_length,
uint8_t* signature, size_t* signature_length) {

View File

@@ -75,6 +75,9 @@ class SessionContext {
const std::vector<uint8_t>& enc_session_key,
const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context);
virtual OEMCryptoResult LoadOemPrivateKey();
virtual OEMCryptoResult PrepAndSignLicenseRequest(uint8_t* message,
size_t message_length,
size_t* core_message_length,