212 lines
6.7 KiB
C++
212 lines
6.7 KiB
C++
// Copyright 2020 Google LLC. All Rights Reserved.
|
|
|
|
#ifndef WHITEBOX_API_LICENSE_BUILDER_H_
|
|
#define WHITEBOX_API_LICENSE_BUILDER_H_
|
|
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "api/test_key_types.h"
|
|
#include "api/test_server.h"
|
|
#include "license_protocol.pb.h"
|
|
|
|
namespace widevine {
|
|
|
|
constexpr size_t kNoProviderKeyId = 0;
|
|
|
|
struct License {
|
|
std::vector<uint8_t> request;
|
|
|
|
std::vector<uint8_t> core_message;
|
|
std::vector<uint8_t> message;
|
|
std::vector<uint8_t> signature;
|
|
|
|
// |session_key_| encrypted using the public key. The white-box expects the
|
|
// session key to be encrypted, so we use the name "session_key_" (even if it
|
|
// is encrypted), we omit the term "encrypted" to match the naming in the API.
|
|
std::vector<uint8_t> session_key;
|
|
};
|
|
|
|
class TestLicenseBuilder {
|
|
public:
|
|
// Signing keys must be 512 bits (64 bytes).
|
|
using SigningKey = std::array<uint8_t, 64>;
|
|
|
|
enum class Padding {
|
|
kNone,
|
|
kPKSC8,
|
|
};
|
|
|
|
enum class RemoteAttestation {
|
|
kUnavailable,
|
|
kVerified,
|
|
kUnverified,
|
|
};
|
|
|
|
enum class VerificationStatus {
|
|
kUnavailable,
|
|
kHardwareVerified,
|
|
kOther,
|
|
};
|
|
|
|
// ODK version of the `core_message`.
|
|
enum class OdkVersion {
|
|
kNone, // No `core_message`
|
|
k16_3, // ODK version 16.3
|
|
k16_5, // ODK version 16.5
|
|
k17_1, // ODK version 17.1
|
|
k18_3, // ODK version 18.3
|
|
|
|
k99, // ODK 16.3, but with the version set to 99 (an arbitrary value).
|
|
};
|
|
|
|
enum class KeyControlBlock {
|
|
kNone,
|
|
kClear,
|
|
kEncrypted,
|
|
};
|
|
|
|
struct Settings {
|
|
Padding padding = Padding::kNone;
|
|
bool simulate_strip_padding_bug = false;
|
|
OdkVersion odk_version = OdkVersion::kNone;
|
|
KeyControlBlock key_control_block = KeyControlBlock::kClear;
|
|
RemoteAttestation remote_attestation = RemoteAttestation::kUnavailable;
|
|
VerificationStatus verification_status = VerificationStatus::kUnavailable;
|
|
|
|
// Flags
|
|
//
|
|
// Default to the "correct" structure. We will flip values to test for
|
|
// invalid states (even if they should never happen). These settings are
|
|
// global since a license server would be more likely to be consistency
|
|
// invalid.
|
|
bool include_content_key_id = true;
|
|
bool include_content_key_key = true;
|
|
bool include_content_key_iv = true;
|
|
bool include_content_key_type = true;
|
|
|
|
bool include_signing_key_iv = true;
|
|
bool include_signing_key_key = true;
|
|
bool include_signing_key_type = true;
|
|
|
|
// Whether to insert an error in the KCB header
|
|
bool kcb_header_error = false;
|
|
|
|
// Our content key's key and ivs should always be 16 bytes (see AesKey
|
|
// definition), but we can use these controls to cut them short. If these
|
|
// values are larger than 16, the key/iv with be padded. In order to
|
|
// override the key size, *_override must be set to true. This is to avoid
|
|
// conflicts between padding and key size.
|
|
bool content_key_key_size_override = false;
|
|
size_t content_key_key_size = 16;
|
|
size_t content_key_iv_size = 16;
|
|
|
|
// Our signing key's key should always be 64 (see SigningKey definition) and
|
|
// the iv size should always be 16 bytes (see AesIV definition), but we can
|
|
// use these controls to cut them short. If these values are larger than 64
|
|
// and 16, the key/iv with be padded. In order to override the key size,
|
|
// *_override must be set to true. This is to avoid conflicts between
|
|
// padding and key size.
|
|
bool signing_key_key_size_override = false;
|
|
size_t signing_key_key_size = 64;
|
|
size_t signing_key_iv_size = 16;
|
|
|
|
// If required, use a ProviderKey when encrypting the content keys.
|
|
// By default, no Provider key is used. Note that the list of available
|
|
// provider keys is fixed.
|
|
size_t provider_key_id = kNoProviderKeyId;
|
|
};
|
|
|
|
// Returns a default signing key that can be used with AddSigningKey().
|
|
static SigningKey DefaultSigningKey();
|
|
|
|
TestLicenseBuilder();
|
|
|
|
void AddSigningKey(const SigningKey& key);
|
|
|
|
void AddContentKey(const ContentKeyData& key);
|
|
|
|
void AddEntitlementKey(const EntitlementKeyData& key);
|
|
|
|
void AddGenericKey(const GenericKeyData& key);
|
|
|
|
// The key id will matter as we will need to reference it, but the key won't
|
|
// matter since we are only using it as a means to verify that a non-content
|
|
// key can't be used as a content key.
|
|
void AddOperatorSessionKey(const KeyId& key_id);
|
|
|
|
void SetSettings(const Settings& settings) { settings_ = settings; }
|
|
Settings& GetSettings() { return settings_; }
|
|
const Settings& GetSettings() const { return settings_; }
|
|
|
|
// Gets the serialized license request and response (in components) that would
|
|
// have been used in the license exchange.
|
|
void Build(const TestServer& server, License* license) const;
|
|
|
|
private:
|
|
const std::array<uint8_t, 16> session_key_ = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
|
|
|
|
video_widevine::LicenseRequest request_;
|
|
video_widevine::License response_;
|
|
std::string serialized_request_;
|
|
// It is `serialized_request_` for license protocol 2.1, and
|
|
// `sha512(serialized_request_)` for license protocol 2.2.
|
|
std::string request_for_key_derivation_;
|
|
std::string container_key_;
|
|
|
|
Settings settings_;
|
|
|
|
std::vector<ContentKeyData> content_keys_;
|
|
std::vector<EntitlementKeyData> entitlement_keys_;
|
|
std::vector<GenericKeyData> generic_keys_;
|
|
std::vector<SigningKey> signing_keys_;
|
|
std::vector<KeyId> operator_session_keys_;
|
|
};
|
|
|
|
inline std::ostream& operator<<(std::ostream& os,
|
|
TestLicenseBuilder::Padding value) {
|
|
switch (value) {
|
|
case TestLicenseBuilder::Padding::kNone:
|
|
return os << "NoPadding";
|
|
case TestLicenseBuilder::Padding::kPKSC8:
|
|
return os << "PKSC8";
|
|
default:
|
|
return os << "<Unknown Padding>";
|
|
}
|
|
}
|
|
|
|
inline std::ostream& operator<<(std::ostream& os,
|
|
TestLicenseBuilder::RemoteAttestation value) {
|
|
switch (value) {
|
|
case TestLicenseBuilder::RemoteAttestation::kUnavailable:
|
|
return os << "RA Unavailable";
|
|
case TestLicenseBuilder::RemoteAttestation::kVerified:
|
|
return os << "RA Verified";
|
|
case TestLicenseBuilder::RemoteAttestation::kUnverified:
|
|
return os << "RA Unverified";
|
|
default:
|
|
return os << "<Unknown RA>";
|
|
}
|
|
}
|
|
|
|
inline std::ostream& operator<<(std::ostream& os,
|
|
TestLicenseBuilder::VerificationStatus value) {
|
|
switch (value) {
|
|
case TestLicenseBuilder::VerificationStatus::kUnavailable:
|
|
return os << "Unverified";
|
|
case TestLicenseBuilder::VerificationStatus::kHardwareVerified:
|
|
return os << "HardwareVerified";
|
|
default:
|
|
return os << "VerifiedOther";
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace widevine
|
|
|
|
#endif // WHITEBOX_API_LICENSE_BUILDER_H_
|