Update to support OEMCrypto v16 with ODK
This commit is contained in:
130
common/rot_id_generator.cc
Normal file
130
common/rot_id_generator.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2019 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:
|
||||
// Classes for generating and decrypting the root of trust id which is
|
||||
// included in generated DRM Certificates.
|
||||
|
||||
#include "common/rot_id_generator.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "common/crypto_util.h"
|
||||
#include "common/ec_key.h"
|
||||
#include "common/rot_id_util.h"
|
||||
#include "common/sha_util.h"
|
||||
#include "common/status.h"
|
||||
#include "protos/public/drm_certificate.pb.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kRotIdLabel[] = "ROOT_OF_TRUST_ID ENCRYPTION LABEL";
|
||||
constexpr int32_t kKeyId = 0;
|
||||
|
||||
std::string GenerateContext(uint32_t system_id) {
|
||||
return absl::StrCat(kRotIdLabel, system_id);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace widevine {
|
||||
|
||||
Status RootOfTrustIdGenerator::Generate(uint32_t system_id,
|
||||
const std::string& unique_id,
|
||||
RootOfTrustId* root_of_trust_id) const {
|
||||
CHECK(root_of_trust_id != nullptr) << "root_of_trust_id was null.";
|
||||
|
||||
if (system_id == 0) {
|
||||
return Status(error::INVALID_ARGUMENT, "system id should not be 0.");
|
||||
}
|
||||
if (unique_id.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT,
|
||||
"The unique id should not be empty.");
|
||||
}
|
||||
|
||||
root_of_trust_id->set_version(
|
||||
widevine::RootOfTrustId::ROOT_OF_TRUST_ID_VERSION_1);
|
||||
root_of_trust_id->set_key_id(kKeyId);
|
||||
if (!ecies_encryptor_->Encrypt(
|
||||
unique_id, GenerateContext(system_id),
|
||||
root_of_trust_id->mutable_encrypted_unique_id())) {
|
||||
root_of_trust_id->Clear();
|
||||
return Status(error::INTERNAL, "Encrypt failed.");
|
||||
}
|
||||
|
||||
std::string unique_id_hash = GenerateUniqueIdHash(unique_id);
|
||||
if (unique_id_hash.empty()) {
|
||||
root_of_trust_id->Clear();
|
||||
return Status(error::INTERNAL, "Could not generate unique id hash.");
|
||||
}
|
||||
|
||||
root_of_trust_id->set_unique_id_hash(GenerateRotIdHash(
|
||||
root_of_trust_id->encrypted_unique_id(), system_id, unique_id_hash));
|
||||
if (root_of_trust_id->unique_id_hash().empty()) {
|
||||
root_of_trust_id->Clear();
|
||||
return Status(error::INTERNAL, "Failed to generate revoked id hash.");
|
||||
}
|
||||
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
std::string RootOfTrustIdGenerator::GenerateUniqueIdHash(
|
||||
const std::string& unique_id) const {
|
||||
return widevine::GenerateUniqueIdHash(unique_id, wv_shared_salt_);
|
||||
}
|
||||
|
||||
Status RootOfTrustIdDecryptor::DecryptUniqueId(
|
||||
uint32_t system_id, const std::string& rot_encrypted_id,
|
||||
std::string* unique_id) const {
|
||||
CHECK(unique_id != nullptr) << "unique_id was null.";
|
||||
if (system_id == 0) {
|
||||
return Status(error::INVALID_ARGUMENT, "system id should not be 0.");
|
||||
}
|
||||
if (rot_encrypted_id.empty()) {
|
||||
return Status(error::INVALID_ARGUMENT,
|
||||
"The rot_encrypted_id should not be empty.");
|
||||
}
|
||||
|
||||
if (!ecies_decryptor_->Decrypt(rot_encrypted_id, GenerateContext(system_id),
|
||||
unique_id)) {
|
||||
return Status(error::INTERNAL, "Failed to decrypt rot_encrypted_id");
|
||||
}
|
||||
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
Status RootOfTrustIdDecryptor::VerifyAndExtractAllValues(
|
||||
uint32_t system_id, const RootOfTrustId& root_of_trust_id,
|
||||
std::string* device_unique_id, std::string* device_unique_id_hash) const {
|
||||
CHECK(device_unique_id != nullptr) << "device_unique_id was null.";
|
||||
CHECK(device_unique_id_hash != nullptr) << "device_unique_id_hash was null.";
|
||||
|
||||
Status status = DecryptUniqueId(
|
||||
system_id, root_of_trust_id.encrypted_unique_id(), device_unique_id);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
*device_unique_id_hash =
|
||||
widevine::GenerateUniqueIdHash(*device_unique_id, wv_shared_salt_);
|
||||
std::string revocation_hash =
|
||||
GenerateRotIdHash(root_of_trust_id.encrypted_unique_id(), system_id,
|
||||
*device_unique_id_hash);
|
||||
// This should not happen unless there's a bug in the way we issue root of
|
||||
// trust ids.
|
||||
if (revocation_hash != root_of_trust_id.unique_id_hash()) {
|
||||
return Status(error::INVALID_ARGUMENT,
|
||||
"The generated revocation hash did not match the one in the "
|
||||
"root_of_trust_id");
|
||||
}
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
Reference in New Issue
Block a user