You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
8.5 KiB
233 lines
8.5 KiB
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <base/files/file_util.h>
|
|
#include <gtest/gtest.h>
|
|
#include <openssl/sha.h>
|
|
|
|
#include "avb_unittest_util.h"
|
|
#include "examples/things/avb_atx_slot_verify.h"
|
|
#include "fake_avb_ops.h"
|
|
|
|
namespace {
|
|
|
|
const char kMetadataPath[] = "test/data/atx_metadata.bin";
|
|
const char kPermanentAttributesPath[] =
|
|
"test/data/atx_permanent_attributes.bin";
|
|
const uint64_t kNewRollbackValue = 42;
|
|
|
|
} /* namespace */
|
|
|
|
namespace avb {
|
|
|
|
// A fixture for testing avb_atx_slot_verify() with ATX. This test is
|
|
// parameterized on the initial stored rollback index (same value used in all
|
|
// relevant locations).
|
|
class AvbAtxSlotVerifyExampleTest
|
|
: public BaseAvbToolTest,
|
|
public FakeAvbOpsDelegateWithDefaults,
|
|
public ::testing::WithParamInterface<uint64_t> {
|
|
public:
|
|
~AvbAtxSlotVerifyExampleTest() override = default;
|
|
|
|
void SetUp() override {
|
|
BaseAvbToolTest::SetUp();
|
|
ReadAtxDefaultData();
|
|
ops_.set_partition_dir(testdir_);
|
|
ops_.set_delegate(this);
|
|
ops_.set_permanent_attributes(attributes_);
|
|
ops_.set_stored_is_device_unlocked(false);
|
|
}
|
|
|
|
// FakeAvbOpsDelegate overrides.
|
|
AvbIOResult validate_vbmeta_public_key(AvbOps* ops,
|
|
const uint8_t* public_key_data,
|
|
size_t public_key_length,
|
|
const uint8_t* public_key_metadata,
|
|
size_t public_key_metadata_length,
|
|
bool* out_key_is_trusted) override {
|
|
// Send to ATX implementation.
|
|
++num_atx_calls_;
|
|
return avb_atx_validate_vbmeta_public_key(ops,
|
|
public_key_data,
|
|
public_key_length,
|
|
public_key_metadata,
|
|
public_key_metadata_length,
|
|
out_key_is_trusted);
|
|
}
|
|
|
|
AvbIOResult write_rollback_index(AvbOps* ops,
|
|
size_t rollback_index_slot,
|
|
uint64_t rollback_index) override {
|
|
num_write_rollback_calls_++;
|
|
return ops_.write_rollback_index(ops, rollback_index_slot, rollback_index);
|
|
}
|
|
|
|
void set_key_version(size_t rollback_index_location,
|
|
uint64_t key_version) override {
|
|
num_key_version_calls_++;
|
|
return ops_.set_key_version(rollback_index_location, key_version);
|
|
}
|
|
|
|
AvbIOResult get_random(size_t num_bytes, uint8_t* output) override {
|
|
return ops_.get_random(num_bytes, output);
|
|
}
|
|
|
|
void RunSlotVerify() {
|
|
ops_.set_stored_rollback_indexes(
|
|
{{0, initial_rollback_value_},
|
|
{AVB_ATX_PIK_VERSION_LOCATION, initial_rollback_value_},
|
|
{AVB_ATX_PSK_VERSION_LOCATION, initial_rollback_value_}});
|
|
std::string metadata_option = "--public_key_metadata=";
|
|
metadata_option += kMetadataPath;
|
|
GenerateVBMetaImage("vbmeta_a.img",
|
|
"SHA512_RSA4096",
|
|
kNewRollbackValue,
|
|
base::FilePath("test/data/testkey_atx_psk.pem"),
|
|
metadata_option);
|
|
SHA256(vbmeta_image_.data(), vbmeta_image_.size(), expected_vbh_extension_);
|
|
|
|
ops_.set_expected_public_key(
|
|
PublicKeyAVB(base::FilePath("test/data/testkey_atx_psk.pem")));
|
|
|
|
AvbSlotVerifyData* slot_data = NULL;
|
|
EXPECT_EQ(expected_result_,
|
|
avb_atx_slot_verify(ops_.avb_atx_ops(),
|
|
"_a",
|
|
lock_state_,
|
|
slot_state_,
|
|
oem_data_state_,
|
|
&slot_data,
|
|
actual_vbh_extension_));
|
|
if (expected_result_ == AVB_SLOT_VERIFY_RESULT_OK) {
|
|
EXPECT_NE(nullptr, slot_data);
|
|
avb_slot_verify_data_free(slot_data);
|
|
// Make sure ATX is being run.
|
|
EXPECT_EQ(1, num_atx_calls_);
|
|
// Make sure we're hooking set_key_version.
|
|
EXPECT_EQ(0, num_key_version_calls_);
|
|
}
|
|
}
|
|
|
|
void CheckVBH() {
|
|
if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
|
|
lock_state_ == AVB_ATX_UNLOCKED) {
|
|
memset(&expected_vbh_extension_, 0, AVB_SHA256_DIGEST_SIZE);
|
|
}
|
|
// Check that the VBH was correctly calculated.
|
|
EXPECT_EQ(0,
|
|
memcmp(actual_vbh_extension_,
|
|
expected_vbh_extension_,
|
|
AVB_SHA256_DIGEST_SIZE));
|
|
}
|
|
|
|
void CheckNewRollbackState() {
|
|
uint64_t expected_rollback_value = kNewRollbackValue;
|
|
if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
|
|
lock_state_ == AVB_ATX_UNLOCKED ||
|
|
slot_state_ != AVB_ATX_SLOT_MARKED_SUCCESSFUL) {
|
|
// Check that rollback indexes were unmodified.
|
|
expected_rollback_value = initial_rollback_value_;
|
|
}
|
|
// Check that all rollback indexes have the expected value.
|
|
std::map<size_t, uint64_t> stored_rollback_indexes =
|
|
ops_.get_stored_rollback_indexes();
|
|
EXPECT_EQ(expected_rollback_value, stored_rollback_indexes[0]);
|
|
EXPECT_EQ(expected_rollback_value,
|
|
stored_rollback_indexes[AVB_ATX_PIK_VERSION_LOCATION]);
|
|
EXPECT_EQ(expected_rollback_value,
|
|
stored_rollback_indexes[AVB_ATX_PSK_VERSION_LOCATION]);
|
|
// Check that if the rollback did not need to change, there were no writes.
|
|
if (initial_rollback_value_ == kNewRollbackValue ||
|
|
initial_rollback_value_ == expected_rollback_value) {
|
|
EXPECT_EQ(0, num_write_rollback_calls_);
|
|
} else {
|
|
EXPECT_NE(0, num_write_rollback_calls_);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
AvbAtxPermanentAttributes attributes_;
|
|
int num_atx_calls_ = 0;
|
|
int num_key_version_calls_ = 0;
|
|
int num_write_rollback_calls_ = 0;
|
|
AvbSlotVerifyResult expected_result_ = AVB_SLOT_VERIFY_RESULT_OK;
|
|
uint64_t initial_rollback_value_ = 0;
|
|
AvbAtxLockState lock_state_ = AVB_ATX_LOCKED;
|
|
AvbAtxSlotState slot_state_ = AVB_ATX_SLOT_MARKED_SUCCESSFUL;
|
|
AvbAtxOemDataState oem_data_state_ = AVB_ATX_OEM_DATA_NOT_USED;
|
|
uint8_t expected_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
|
|
uint8_t actual_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
|
|
|
|
private:
|
|
void ReadAtxDefaultData() {
|
|
std::string tmp;
|
|
ASSERT_TRUE(
|
|
base::ReadFileToString(base::FilePath(kPermanentAttributesPath), &tmp));
|
|
ASSERT_EQ(tmp.size(), sizeof(AvbAtxPermanentAttributes));
|
|
memcpy(&attributes_, tmp.data(), tmp.size());
|
|
}
|
|
};
|
|
|
|
TEST_P(AvbAtxSlotVerifyExampleTest, RunWithStartingIndex) {
|
|
initial_rollback_value_ = GetParam();
|
|
RunSlotVerify();
|
|
CheckVBH();
|
|
CheckNewRollbackState();
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(P,
|
|
AvbAtxSlotVerifyExampleTest,
|
|
::testing::Values(0,
|
|
1,
|
|
kNewRollbackValue / 2,
|
|
kNewRollbackValue - 1,
|
|
kNewRollbackValue));
|
|
|
|
TEST_F(AvbAtxSlotVerifyExampleTest, RunUnlocked) {
|
|
lock_state_ = AVB_ATX_UNLOCKED;
|
|
RunSlotVerify();
|
|
CheckVBH();
|
|
CheckNewRollbackState();
|
|
}
|
|
|
|
TEST_F(AvbAtxSlotVerifyExampleTest, RunWithSlotNotMarkedSuccessful) {
|
|
slot_state_ = AVB_ATX_SLOT_NOT_MARKED_SUCCESSFUL;
|
|
RunSlotVerify();
|
|
CheckVBH();
|
|
CheckNewRollbackState();
|
|
}
|
|
|
|
TEST_F(AvbAtxSlotVerifyExampleTest, RunWithOemData) {
|
|
oem_data_state_ = AVB_ATX_OEM_DATA_USED;
|
|
RunSlotVerify();
|
|
CheckVBH();
|
|
CheckNewRollbackState();
|
|
}
|
|
|
|
} // namespace avb
|