Files
whitebox/whitebox/api/license_whitebox_query_signing_key_status_test.cc
Aaron Vaage f936dd2983 Add "License Key Mode" To API
In order to support both single-key and dual-key RSA implementations
where single-key will use key 0 for both sign and encryption and where
dual-key will use key 0 for sign and key 1 for encryption.

Additional changes in this code drop:

 - Added VMP / RA override enabled tests
 - Added VMP / RA override disabled tests

This brings the partner repo in sync with the internal repo at
commit 71760b6da1ec546c65b56e2f86b39b73b53f6734.
2021-04-05 12:05:15 -07:00

275 lines
9.4 KiB
C++

// Copyright 2021 Google LLC. All Rights Reserved.
#include "api/license_whitebox.h"
#include <memory>
#include <string>
#include <vector>
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_license_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace widevine {
using OdkVersion = TestLicenseBuilder::OdkVersion;
using KeyControlBlock = TestLicenseBuilder::KeyControlBlock;
enum class LicenseParsing {
kUseProtobuf,
kUseOdk,
};
class LicenseWhiteboxQuerySigningKeyStatus
: public LicenseWhiteboxTestBase,
public testing::WithParamInterface<LicenseParsing> {
protected:
void SetUp() override {
LicenseWhiteboxTestBase::SetUp();
signing_key_ = TestLicenseBuilder::DefaultSigningKey();
license_parsing_ = GetParam();
}
void SetSettings(const TestLicenseBuilder::Settings& settings) {
builder_.SetSettings(settings);
}
void AddSigningKey() { builder_.AddSigningKey(signing_key_); }
WB_Result LoadLicense() {
// To use ODK, we need to use 16.5 (which should have a clear KCB). If we
// want to force Protobuf parsing, we just ned to have no ODK message and/or
// an encrypted KCB.
switch (license_parsing_) {
case LicenseParsing::kUseProtobuf:
builder_.GetSettings().odk_version = OdkVersion::kNone;
builder_.GetSettings().key_control_block = KeyControlBlock::kEncrypted;
break;
case LicenseParsing::kUseOdk:
builder_.GetSettings().odk_version = OdkVersion::k16_5;
builder_.GetSettings().key_control_block = KeyControlBlock::kClear;
break;
default:
// We can't use an assert here (wrong return type) so instead we'll
// return an error code.
return WB_RESULT_INVALID_PARAMETER;
}
// ODK requires there to be at least one content key or else it will fail
// to create the core message.
const auto& content_key = &golden_data_.CBCCryptoKey();
builder_.AddContentKey(content_key->level, content_key->id,
content_key->content->key);
auto server = TestServer::CreateDualKey();
License license;
builder_.Build(*server, &license);
return WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.request.size());
}
private:
TestLicenseBuilder builder_;
TestLicenseBuilder::SigningKey signing_key_;
LicenseParsing license_parsing_;
};
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, ValidKey) {
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, NoKey) {
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_KEY_UNAVAILABLE);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, IgnoresContentKeyParams) {
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
// The key id value really does not matter. What matters is that it will be
// present and therefore the white-box should just ignore it since we are
// doing a signing key query.
const uint8_t key_id[] = {0x00, 0x01, 0x02, 0x03};
const size_t key_id_size = sizeof(key_id);
WB_KeyStatus key_state;
// Try every permutation of content key params (many invalid for content keys)
// to make sure that the signing key query ignores them.
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
key_id, key_id_size, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
key_id, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, key_id_size, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidParameterForNullWhitebox) {
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(nullptr, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidParameterForNullKeyStatus) {
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, nullptr),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidStateForNoLicense) {
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_INVALID_STATE);
}
// If there is no key type, ODK will assume that it is a signing key. So the
// protobuf parser should also do this. This is because protobuf will default
// to the first enum value when the value is missing.
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, ValidKeyForNoKeyType) {
TestLicenseBuilder::Settings settings;
settings.include_signing_key_type = false;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_SIGNING_KEY_VALID);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidKeyForNoIv) {
TestLicenseBuilder::Settings settings;
settings.include_signing_key_iv = false;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_INVALID);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidKeyForShortIv) {
TestLicenseBuilder::Settings settings;
settings.signing_key_iv_size = 7;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_INVALID);
}
// The ODK will not write the key to the core message if there is no key data.
// This is odd, since it does not check any other fields.
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, KeyNotFoundForNoKeyData) {
TestLicenseBuilder::Settings settings;
settings.include_signing_key_key = false;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_KEY_UNAVAILABLE);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidKeyForShortKeyData) {
TestLicenseBuilder::Settings settings;
settings.signing_key_key_size_override = true;
settings.signing_key_key_size = 7;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_INVALID);
}
TEST_P(LicenseWhiteboxQuerySigningKeyStatus, InvalidKeyForLongKeyData) {
TestLicenseBuilder::Settings settings;
settings.signing_key_key_size_override = true;
settings.signing_key_key_size = 100;
SetSettings(settings);
AddSigningKey();
ASSERT_EQ(LoadLicense(), WB_RESULT_OK);
WB_KeyStatus key_state;
ASSERT_EQ(WB_License_QueryKeyStatus(whitebox_, WB_KEY_QUERY_TYPE_SIGNING_KEY,
nullptr, 0, &key_state),
WB_RESULT_OK);
ASSERT_EQ(key_state, WB_KEY_STATUS_INVALID);
}
INSTANTIATE_TEST_SUITE_P(ProtbufParsing,
LicenseWhiteboxQuerySigningKeyStatus,
::testing::Values(LicenseParsing::kUseProtobuf));
INSTANTIATE_TEST_SUITE_P(OdkParsing,
LicenseWhiteboxQuerySigningKeyStatus,
::testing::Values(LicenseParsing::kUseOdk));
} // namespace widevine