Files
whitebox/whitebox/api/test_license_builder.h
2023-07-20 21:32:51 +00:00

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_