Update to support OEMCrypto v16 with ODK
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "base/thread_annotations.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "util/gtl/map_util.h"
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "common/drm_root_certificate.h"
|
||||
#include "common/error_space.h"
|
||||
#include "common/rsa_util.h"
|
||||
#include "common/status.h"
|
||||
#include "protos/public/client_identification.pb.h"
|
||||
#include "protos/public/drm_certificate.pb.h"
|
||||
#include "protos/public/errors.pb.h"
|
||||
@@ -44,16 +45,18 @@ class DrmServiceCertificateMap {
|
||||
void AddCert(std::unique_ptr<DrmServiceCertificate> new_cert);
|
||||
void ClearDefaultDrmServiceCertificate();
|
||||
const DrmServiceCertificate* GetDefaultCert();
|
||||
const DrmServiceCertificate* GetCert(const std::string& serial_number);
|
||||
|
||||
const DrmServiceCertificate* GetCertBySerialNumber(
|
||||
const std::string& serial_number);
|
||||
const DrmServiceCertificate* GetCertByProvider(
|
||||
const std::string& provider_id);
|
||||
static DrmServiceCertificateMap* GetInstance();
|
||||
|
||||
private:
|
||||
absl::Mutex mutex_;
|
||||
// Certificate serial number to certificate map.
|
||||
std::map<std::string, std::unique_ptr<DrmServiceCertificate>> map_
|
||||
GUARDED_BY(mutex_);
|
||||
DrmServiceCertificate* default_cert_ GUARDED_BY(mutex_);
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
DrmServiceCertificate* default_cert_ ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
DrmServiceCertificateMap::DrmServiceCertificateMap() : default_cert_(nullptr) {}
|
||||
@@ -94,12 +97,30 @@ const DrmServiceCertificate* DrmServiceCertificateMap::GetDefaultCert() {
|
||||
return default_cert_;
|
||||
}
|
||||
|
||||
const DrmServiceCertificate* DrmServiceCertificateMap::GetCert(
|
||||
const DrmServiceCertificate* DrmServiceCertificateMap::GetCertBySerialNumber(
|
||||
const std::string& serial_number) {
|
||||
absl::ReaderMutexLock lock(&mutex_);
|
||||
return map_[serial_number].get();
|
||||
}
|
||||
|
||||
const DrmServiceCertificate* DrmServiceCertificateMap::GetCertByProvider(
|
||||
const std::string& provider_id) {
|
||||
absl::ReaderMutexLock lock(&mutex_);
|
||||
DrmServiceCertificate* provider_drm_cert = nullptr;
|
||||
for (const auto& drm_cert : map_) {
|
||||
if (drm_cert.second->provider_id() == provider_id) {
|
||||
if (provider_drm_cert == nullptr) {
|
||||
provider_drm_cert = drm_cert.second.get();
|
||||
} else if (drm_cert.second->creation_time_seconds() >
|
||||
provider_drm_cert->creation_time_seconds()) {
|
||||
// Use the newest cert.
|
||||
provider_drm_cert = drm_cert.second.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return provider_drm_cert;
|
||||
}
|
||||
|
||||
DrmServiceCertificateMap* DrmServiceCertificateMap::GetInstance() {
|
||||
static auto* const kInstance = new DrmServiceCertificateMap();
|
||||
return kInstance;
|
||||
@@ -108,7 +129,8 @@ DrmServiceCertificateMap* DrmServiceCertificateMap::GetInstance() {
|
||||
} // namespace
|
||||
|
||||
Status DrmServiceCertificate::AddDrmServiceCertificate(
|
||||
const DrmRootCertificate* root_drm_cert, const std::string& service_certificate,
|
||||
const DrmRootCertificate* root_drm_cert,
|
||||
const std::string& service_certificate,
|
||||
const std::string& service_private_key,
|
||||
const std::string& service_private_key_passphrase) {
|
||||
DrmCertificate drm_cert;
|
||||
@@ -166,13 +188,22 @@ DrmServiceCertificate::GetDefaultDrmServiceCertificateOrDie() {
|
||||
return default_cert;
|
||||
}
|
||||
|
||||
const DrmServiceCertificate* DrmServiceCertificate::GetDrmServiceCertificate(
|
||||
const DrmServiceCertificate*
|
||||
DrmServiceCertificate::GetDrmServiceCertificateBySerialNumber(
|
||||
const std::string& serial_number) {
|
||||
return DrmServiceCertificateMap::GetInstance()->GetCert(serial_number);
|
||||
return DrmServiceCertificateMap::GetInstance()->GetCertBySerialNumber(
|
||||
serial_number);
|
||||
}
|
||||
|
||||
const DrmServiceCertificate*
|
||||
DrmServiceCertificate::GetDrmServiceCertificateByProvider(
|
||||
const std::string& provider) {
|
||||
return DrmServiceCertificateMap::GetInstance()->GetCertByProvider(provider);
|
||||
}
|
||||
|
||||
Status DrmServiceCertificate::SetDefaultDrmServiceCertificate(
|
||||
const DrmRootCertificate* root_drm_cert, const std::string& service_certificate,
|
||||
const DrmRootCertificate* root_drm_cert,
|
||||
const std::string& service_certificate,
|
||||
const std::string& service_private_key,
|
||||
const std::string& service_private_key_passphrase) {
|
||||
DrmServiceCertificateMap::GetInstance()->ClearDefaultDrmServiceCertificate();
|
||||
@@ -185,60 +216,22 @@ Status DrmServiceCertificate::DecryptClientIdentification(
|
||||
const EncryptedClientIdentification& encrypted_client_id,
|
||||
ClientIdentification* client_id) {
|
||||
DCHECK(client_id);
|
||||
if (encrypted_client_id.service_certificate_serial_number().empty()) {
|
||||
std::string serialized_client_id;
|
||||
Status status = DecryptEncryptedPayload(
|
||||
encrypted_client_id.service_certificate_serial_number(),
|
||||
encrypted_client_id.provider_id(),
|
||||
encrypted_client_id.encrypted_client_id(),
|
||||
encrypted_client_id.encrypted_client_id_iv(),
|
||||
encrypted_client_id.encrypted_privacy_key(), &serialized_client_id);
|
||||
if (status.error_code() == error::INVALID_ARGUMENT) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"missing-service-certificate-serial-number");
|
||||
status.error_message());
|
||||
}
|
||||
if (encrypted_client_id.provider_id().empty()) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"missing-service-id");
|
||||
}
|
||||
if (encrypted_client_id.encrypted_client_id().empty()) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"missing-encrypted-client-id");
|
||||
}
|
||||
if (encrypted_client_id.encrypted_client_id_iv().empty()) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"missing-encrypted-client-id-iv");
|
||||
}
|
||||
if (encrypted_client_id.encrypted_privacy_key().empty()) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"missing-encrypted-privacy-key");
|
||||
}
|
||||
std::string privacy_key;
|
||||
std::string provider_id;
|
||||
const DrmServiceCertificate* cert = GetDrmServiceCertificate(
|
||||
encrypted_client_id.service_certificate_serial_number());
|
||||
if (!cert) {
|
||||
return Status(
|
||||
error_space, SERVICE_CERTIFICATE_NOT_FOUND,
|
||||
"service-certificate-not-found (SN " +
|
||||
absl::BytesToHexString(
|
||||
encrypted_client_id.service_certificate_serial_number()) +
|
||||
")");
|
||||
}
|
||||
if (!cert->private_key()->Decrypt(encrypted_client_id.encrypted_privacy_key(),
|
||||
&privacy_key)) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"privacy-key-decryption-failed");
|
||||
}
|
||||
if (cert->provider_id() != encrypted_client_id.provider_id()) {
|
||||
return Status(error_space, SERVICE_CERTIFICATE_NOT_FOUND,
|
||||
std::string("provider-id-mismatch (") + cert->provider_id() +
|
||||
" / " + encrypted_client_id.provider_id() + ")");
|
||||
}
|
||||
std::string serialized_client_id(crypto_util::DecryptAesCbc(
|
||||
privacy_key, encrypted_client_id.encrypted_client_id_iv(),
|
||||
encrypted_client_id.encrypted_client_id()));
|
||||
if (serialized_client_id.empty()) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"client-id-decryption-failed");
|
||||
}
|
||||
if (!client_id->ParseFromString(serialized_client_id)) {
|
||||
if (status.ok() && !client_id->ParseFromString(serialized_client_id)) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION,
|
||||
"client-id-parse-failed");
|
||||
}
|
||||
return OkStatus();
|
||||
return status;
|
||||
}
|
||||
|
||||
void DrmServiceCertificate::ResetServiceCertificates() {
|
||||
@@ -271,6 +264,67 @@ Status DrmServiceCertificate::ValidateDrmServiceCertificate() {
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
Status DrmServiceCertificate::DecryptLicenseChallenge(
|
||||
const EncryptedLicenseRequest& encrypted_license_request,
|
||||
std::string* license_challenge) {
|
||||
Status status = DecryptEncryptedPayload(
|
||||
encrypted_license_request.service_certificate_serial_number(),
|
||||
encrypted_license_request.provider_id(),
|
||||
encrypted_license_request.encrypted_license_request(),
|
||||
encrypted_license_request.encrypted_license_request_iv(),
|
||||
encrypted_license_request.encrypted_privacy_key(), license_challenge);
|
||||
if (status.error_code() == error::INVALID_ARGUMENT) {
|
||||
return Status(error_space, INVALID_ENCRYPTED_LICENSE_CHALLENGE,
|
||||
status.error_message());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DrmServiceCertificate::DecryptEncryptedPayload(
|
||||
const std::string& service_certificate_serial_number,
|
||||
const std::string& provider_id, const std::string& encrypted_payload,
|
||||
const std::string& iv, const std::string& encrypted_privacy_key,
|
||||
std::string* payload) {
|
||||
if (payload == nullptr) {
|
||||
return Status(error::INVALID_ARGUMENT, "null-payload");
|
||||
}
|
||||
payload->clear();
|
||||
if (service_certificate_serial_number.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT,
|
||||
"missing-service-certificate-serial-number");
|
||||
} else if (provider_id.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT, "missing-service-id");
|
||||
} else if (encrypted_payload.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT, "missing-encrypted-payload");
|
||||
} else if (iv.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT, "missing-iv");
|
||||
} else if (encrypted_privacy_key.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT, "missing-privacy-key");
|
||||
}
|
||||
std::string privacy_key;
|
||||
const DrmServiceCertificate* cert =
|
||||
GetDrmServiceCertificateBySerialNumber(service_certificate_serial_number);
|
||||
if (!cert) {
|
||||
return Status(
|
||||
error_space, SERVICE_CERTIFICATE_NOT_FOUND,
|
||||
"service-certificate-not-found (SN " +
|
||||
absl::BytesToHexString(service_certificate_serial_number) + ")");
|
||||
}
|
||||
if (!cert->private_key()->Decrypt(encrypted_privacy_key, &privacy_key)) {
|
||||
return Status(error::INVALID_ARGUMENT, "privacy-key-decryption-failed");
|
||||
}
|
||||
if (cert->provider_id() != provider_id) {
|
||||
return Status(error_space, SERVICE_CERTIFICATE_NOT_FOUND,
|
||||
std::string("provider-id-mismatch (") + cert->provider_id() +
|
||||
" / " + provider_id + ")");
|
||||
}
|
||||
*payload = crypto_util::DecryptAesCbc(privacy_key, iv, encrypted_payload);
|
||||
if (payload->empty()) {
|
||||
return Status(error::INVALID_ARGUMENT, "payload-decryption-failed");
|
||||
}
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
DrmServiceCertificate::DrmServiceCertificate(
|
||||
const std::string& service_certificate, const std::string& provider_id,
|
||||
const std::string& serial_number, const uint32_t creation_time_seconds,
|
||||
|
||||
Reference in New Issue
Block a user