Files
whitebox/api/license_whitebox_get_secret_string_test.cc
Aaron Vaage 41e86ecab9 Code Drop Three (Update Two)
In this update we have:

  - Added the verified platform tests. These tests show how some
    platforms, when verified are allowed to by pass the normal policy
    restrictions. This is done with ChromeOS, thus the name of the
    tests use "chrome_os".

  - Removed WB_RESULT_INVALID_PADDING. This error was when we the
    non-license APIs exposed a AES function with padding. However,
    those functions have been removed from the API and this error is
    no longer used by the API.

  - Tests have been updated to avoid signed-vs-unsigned comparison
    and to use the Chromium path to gTest (which is mocked in this
    library).

  - Tests have been updated to use a new test base and golden data
    system to make them easier to read.
2020-05-30 11:34:32 -07:00

256 lines
9.7 KiB
C++

// Copyright 2020 Google LLC. All Rights Reserved.
#include "api/license_whitebox.h"
#include <string>
#include <vector>
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/rsa_key.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace widevine {
class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase {
protected:
void SetUp() override {
LicenseWhiteboxTestBase::SetUp();
// The secret string size is implementation specific, so this number just
// needs to be reasonably large to accommodate different implementations.
secret_string_size_ = 256;
secret_string_.resize(secret_string_size_);
golden_data_.MakeKeyIdDifferent(&non_content_key_id_);
golden_data_.MakeKeyIdDifferent(&missing_key_id_);
}
void LoadLicense() {
TestLicenseBuilder builder;
builder.AddContentKey(golden_data_.CBCCryptoKey().level,
golden_data_.CBCCryptoKey().id,
golden_data_.CBCCryptoKey().content->key);
builder.AddContentKey(golden_data_.CBCDecodeKey().level,
golden_data_.CBCDecodeKey().id,
golden_data_.CBCDecodeKey().content->key);
builder.AddContentKey(golden_data_.CBCHardwareKey().level,
golden_data_.CBCHardwareKey().id,
golden_data_.CBCHardwareKey().content->key);
builder.AddOperatorSessionKey(non_content_key_id_);
License license;
builder.Build(*public_key_, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, 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()),
WB_RESULT_OK);
}
// We need two special keys for this test, one that will be used for a
// non-content key and one that will never be in the license.
std::vector<uint8_t> non_content_key_id_ = {0, 0, 0};
std::vector<uint8_t> missing_key_id_ = {1, 0, 0};
size_t secret_string_size_;
std::vector<uint8_t> secret_string_;
};
TEST_F(LicenseWhiteboxGetSecretStringTest, SuccessForCBCWithCryptoKey) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_OK);
ASSERT_GT(secret_string_size_, 0u);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, SuccessForCTRWithCryptoKey) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_OK);
ASSERT_GT(secret_string_size_, 0u);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, SuccessForCBCWithDecodeKey) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCDecodeKey().id.data(),
golden_data_.CBCDecodeKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_OK);
ASSERT_GT(secret_string_size_, 0u);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, SuccessForCTRWithDecodeKey) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CBCDecodeKey().id.data(),
golden_data_.CBCDecodeKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_OK);
ASSERT_GT(secret_string_size_, 0u);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, InvalidParameterForNullWhitebox) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(nullptr, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxGetSecretStringTest,
InvalidParameterForInvalidCipherMode) {
LoadLicense();
// In order to trick the compiler into letting us pass an invalid enum value
// to WB__License_Decrypt(), we need to cast it. If we don't do this, the
// compiler tries to save us.
const WB_CipherMode invalid_mode = static_cast<WB_CipherMode>(0xFF);
ASSERT_EQ(WB_License_GetSecretString(
whitebox_, invalid_mode, golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(), secret_string_.data(),
&secret_string_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, InvalidParameterForNullKeyId) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC, nullptr,
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, InvalidParameterForZeroKeyIdSize) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(), 0,
secret_string_.data(), &secret_string_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxGetSecretStringTest,
InvalidParameterForNullSecretString) {
LoadLicense();
ASSERT_EQ(WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
nullptr, &secret_string_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxGetSecretStringTest,
InvalidParameterForNullSecretStringSize) {
LoadLicense();
ASSERT_EQ(WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), nullptr),
WB_RESULT_INVALID_PARAMETER);
}
// For this test, "missing key id" specifically means a key id that was never
// in the license to start with. This is different than "non content key"
// and "dropped content key", as those keys were in the license but ignored.
TEST_F(LicenseWhiteboxGetSecretStringTest, KeyUnavailableForMissingKeyId) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
missing_key_id_.data(), missing_key_id_.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_KEY_UNAVAILABLE);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, KeyUnavailableForNonContentKey) {
LoadLicense();
ASSERT_EQ(WB_License_GetSecretString(
whitebox_, WB_CIPHER_MODE_CBC, non_content_key_id_.data(),
non_content_key_id_.size(), secret_string_.data(),
&secret_string_size_),
WB_RESULT_KEY_UNAVAILABLE);
}
// Under normal circumstances, a hardware key should be dropped. The exception
// to this rule is on ChromeOS with a special license.
TEST_F(LicenseWhiteboxGetSecretStringTest,
InsufficientSecurityLevelForHardwareContentKey) {
LoadLicense();
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCHardwareKey().id.data(),
golden_data_.CBCHardwareKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_INSUFFICIENT_SECURITY_LEVEL);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, BufferTooSmall) {
LoadLicense();
// Since the secret string is implementation specific, we don't want to make
// any big assumptions about what would be too small. Using 1 is fairly safe
// as it would not introduce enough variation to be effective. We avoid using
// zero here so that we can verify that we are not just checking for zero.
secret_string_size_ = 1;
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_BUFFER_TOO_SMALL);
// Make sure that the output included the required size. We don't know what
// it is, so we rely on checking that it is just bigger than the "too small"
// size.
ASSERT_GT(secret_string_size_, 1u);
}
TEST_F(LicenseWhiteboxGetSecretStringTest, InvalidState) {
// Purposely do not load a license so that we won't have any keys, causing
// use to be in an invalid state.
ASSERT_EQ(
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCCryptoKey().id.data(),
golden_data_.CBCCryptoKey().id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_INVALID_STATE);
}
} // namespace widevine