diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp index 984de937..b62cd39f 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp @@ -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 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 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 AuthenticationRoot::DeviceId() const { } if (prov_method_ == OEMCrypto_Keybox) { LOGE("Expected keybox to be set for a device ID"); - return kEmptyVector; + return std::vector(); } return std::vector(kFakeDeviceId.begin(), kFakeDeviceId.end()); } @@ -311,7 +312,7 @@ std::vector AuthenticationRoot::DeviceKey() const { return kb->DeviceKey(); } LOGE("No device key has been set"); - return kEmptyVector; + return std::vector(); } 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 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 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& 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 diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h index 9050b983..c1ae01db 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h @@ -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 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& GetOemPrivateKey() const; + std::shared_ptr ShareOemCertKey() { return oem_cert_key_; } + RsaPrivateKey* OemCertKey() const { return oem_cert_key_.get(); } + bool HasOemCertKey() const { return static_cast(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 rsa_key_; - std::shared_ptr test_rsa_key_; + std::shared_ptr drm_cert_key_; + std::shared_ptr test_drm_cert_key_; // Keybox data. std::unique_ptr keybox_; std::unique_ptr test_keybox_; + // OEM certificate. + std::unique_ptr oem_cert_; + std::shared_ptr oem_cert_key_; + CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot); }; } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp index 3b17bb63..96134b99 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp @@ -24,6 +24,15 @@ class Prov30CryptoEngine : public CryptoEngine { explicit Prov30CryptoEngine(std::unique_ptr&& 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. diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h index 70613aff..0fddd30f 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h @@ -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 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 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; } diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp index 09b78315..0f65f489 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -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, diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index 69e219f6..96f0b8ea 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -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) { diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h index fe942ad6..e01054eb 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h @@ -75,6 +75,9 @@ class SessionContext { const std::vector& enc_session_key, const std::vector& mac_context, const std::vector& enc_context); + + virtual OEMCryptoResult LoadOemPrivateKey(); + virtual OEMCryptoResult PrepAndSignLicenseRequest(uint8_t* message, size_t message_length, size_t* core_message_length,