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.
1045 lines
37 KiB
1045 lines
37 KiB
/*
|
|
* Copyright (C) 2016 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/objects.h>
|
|
#include <openssl/pem.h>
|
|
#include <openssl/rsa.h>
|
|
#include <openssl/sha.h>
|
|
|
|
#include <libavb_atx/libavb_atx.h>
|
|
|
|
#include "avb_unittest_util.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 char kPRKPrivateKeyPath[] = "test/data/testkey_atx_prk.pem";
|
|
const char kPIKPrivateKeyPath[] = "test/data/testkey_atx_pik.pem";
|
|
const char kPSKPrivateKeyPath[] = "test/data/testkey_atx_psk.pem";
|
|
const char kPUKPrivateKeyPath[] = "test/data/testkey_atx_puk.pem";
|
|
const char kUnlockChallengePath[] = "test/data/atx_unlock_challenge.bin";
|
|
const char kUnlockCredentialPath[] = "test/data/atx_unlock_credential.bin";
|
|
|
|
class ScopedRSA {
|
|
public:
|
|
ScopedRSA(const char* pem_key_path) {
|
|
FILE* file = fopen(pem_key_path, "r");
|
|
rsa_ = PEM_read_RSAPrivateKey(file, nullptr, nullptr, nullptr);
|
|
fclose(file);
|
|
}
|
|
|
|
~ScopedRSA() {
|
|
if (rsa_) {
|
|
RSA_free(rsa_);
|
|
}
|
|
}
|
|
|
|
// PKCS #1 v1.5 signature using SHA512. Returns true on success.
|
|
bool Sign(const void* data_to_sign, size_t length, uint8_t signature[]) {
|
|
uint8_t digest[AVB_SHA512_DIGEST_SIZE];
|
|
const unsigned char* data_to_sign_buf =
|
|
reinterpret_cast<const unsigned char*>(data_to_sign);
|
|
SHA512(data_to_sign_buf, length, digest);
|
|
unsigned int signature_length = 0;
|
|
return (1 == RSA_sign(NID_sha512,
|
|
digest,
|
|
AVB_SHA512_DIGEST_SIZE,
|
|
signature,
|
|
&signature_length,
|
|
rsa_));
|
|
}
|
|
|
|
private:
|
|
RSA* rsa_;
|
|
};
|
|
|
|
} /* namespace */
|
|
|
|
namespace avb {
|
|
|
|
class AvbAtxValidateTest : public ::testing::Test,
|
|
public FakeAvbOpsDelegateWithDefaults {
|
|
public:
|
|
~AvbAtxValidateTest() override {}
|
|
|
|
void SetUp() override {
|
|
ReadDefaultData();
|
|
ops_.set_delegate(this);
|
|
ops_.set_permanent_attributes(attributes_);
|
|
ops_.set_stored_rollback_indexes(
|
|
{{AVB_ATX_PIK_VERSION_LOCATION, 0}, {AVB_ATX_PSK_VERSION_LOCATION, 0}});
|
|
}
|
|
|
|
// FakeAvbOpsDelegate methods.
|
|
AvbIOResult read_from_partition(const char* partition,
|
|
int64_t offset,
|
|
size_t num_bytes,
|
|
void* buffer,
|
|
size_t* out_num_read) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult get_preloaded_partition(
|
|
const char* partition,
|
|
size_t num_bytes,
|
|
uint8_t** out_pointer,
|
|
size_t* out_num_bytes_preloaded) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult write_to_partition(const char* partition,
|
|
int64_t offset,
|
|
size_t num_bytes,
|
|
const void* buffer) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
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 {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult read_rollback_index(AvbOps* ops,
|
|
size_t rollback_index_slot,
|
|
uint64_t* out_rollback_index) override {
|
|
if ((fail_read_pik_rollback_index_ &&
|
|
rollback_index_slot == AVB_ATX_PIK_VERSION_LOCATION) ||
|
|
(fail_read_psk_rollback_index_ &&
|
|
rollback_index_slot == AVB_ATX_PSK_VERSION_LOCATION)) {
|
|
return AVB_IO_RESULT_ERROR_IO;
|
|
}
|
|
return ops_.read_rollback_index(
|
|
ops, rollback_index_slot, out_rollback_index);
|
|
}
|
|
|
|
AvbIOResult write_rollback_index(AvbOps* ops,
|
|
size_t rollback_index_slot,
|
|
uint64_t rollback_index) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult read_is_device_unlocked(AvbOps* ops,
|
|
bool* out_is_device_unlocked) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult get_unique_guid_for_partition(AvbOps* ops,
|
|
const char* partition,
|
|
char* guid_buf,
|
|
size_t guid_buf_size) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult get_size_of_partition(AvbOps* ops,
|
|
const char* partition,
|
|
uint64_t* out_size) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
|
}
|
|
|
|
AvbIOResult read_persistent_value(const char* name,
|
|
size_t buffer_size,
|
|
uint8_t* out_buffer,
|
|
size_t* out_num_bytes_read) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
|
|
}
|
|
|
|
AvbIOResult write_persistent_value(const char* name,
|
|
size_t value_size,
|
|
const uint8_t* value) override {
|
|
// Expect method not used.
|
|
return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
|
|
}
|
|
|
|
AvbIOResult read_permanent_attributes(
|
|
AvbAtxPermanentAttributes* attributes) override {
|
|
if (fail_read_permanent_attributes_) {
|
|
return AVB_IO_RESULT_ERROR_IO;
|
|
}
|
|
return ops_.read_permanent_attributes(attributes);
|
|
}
|
|
|
|
AvbIOResult read_permanent_attributes_hash(
|
|
uint8_t hash[AVB_SHA256_DIGEST_SIZE]) override {
|
|
if (fail_read_permanent_attributes_hash_) {
|
|
return AVB_IO_RESULT_ERROR_IO;
|
|
}
|
|
return ops_.read_permanent_attributes_hash(hash);
|
|
}
|
|
|
|
void set_key_version(size_t rollback_index_location,
|
|
uint64_t key_version) override {
|
|
ops_.set_key_version(rollback_index_location, key_version);
|
|
}
|
|
|
|
AvbIOResult get_random(size_t num_bytes, uint8_t* output) override {
|
|
if (fail_get_random_) {
|
|
return AVB_IO_RESULT_ERROR_IO;
|
|
}
|
|
if (fake_random_.size() >= num_bytes) {
|
|
memcpy(output, fake_random_.data(), num_bytes);
|
|
return AVB_IO_RESULT_OK;
|
|
}
|
|
return ops_.get_random(num_bytes, output);
|
|
}
|
|
|
|
protected:
|
|
virtual AvbIOResult Validate(bool* is_trusted) {
|
|
return avb_atx_validate_vbmeta_public_key(
|
|
ops_.avb_ops(),
|
|
metadata_.product_signing_key_certificate.signed_data.public_key,
|
|
AVB_ATX_PUBLIC_KEY_SIZE,
|
|
reinterpret_cast<const uint8_t*>(&metadata_),
|
|
sizeof(metadata_),
|
|
is_trusted);
|
|
}
|
|
|
|
AvbIOResult ValidateUnlock(bool* is_trusted) {
|
|
return avb_atx_validate_unlock_credential(
|
|
ops_.avb_atx_ops(), &unlock_credential_, is_trusted);
|
|
}
|
|
|
|
void SignPIKCertificate() {
|
|
memset(metadata_.product_intermediate_key_certificate.signature,
|
|
0,
|
|
AVB_RSA4096_NUM_BYTES);
|
|
ScopedRSA key(kPRKPrivateKeyPath);
|
|
ASSERT_TRUE(
|
|
key.Sign(&metadata_.product_intermediate_key_certificate.signed_data,
|
|
sizeof(AvbAtxCertificateSignedData),
|
|
metadata_.product_intermediate_key_certificate.signature));
|
|
}
|
|
|
|
void SignPSKCertificate() {
|
|
memset(metadata_.product_signing_key_certificate.signature,
|
|
0,
|
|
AVB_RSA4096_NUM_BYTES);
|
|
ScopedRSA key(kPIKPrivateKeyPath);
|
|
ASSERT_TRUE(key.Sign(&metadata_.product_signing_key_certificate.signed_data,
|
|
sizeof(AvbAtxCertificateSignedData),
|
|
metadata_.product_signing_key_certificate.signature));
|
|
}
|
|
|
|
void SignUnlockCredentialPIKCertificate() {
|
|
memset(unlock_credential_.product_intermediate_key_certificate.signature,
|
|
0,
|
|
AVB_RSA4096_NUM_BYTES);
|
|
ScopedRSA key(kPRKPrivateKeyPath);
|
|
ASSERT_TRUE(key.Sign(
|
|
&unlock_credential_.product_intermediate_key_certificate.signed_data,
|
|
sizeof(AvbAtxCertificateSignedData),
|
|
unlock_credential_.product_intermediate_key_certificate.signature));
|
|
}
|
|
|
|
void SignUnlockCredentialPUKCertificate() {
|
|
memset(unlock_credential_.product_unlock_key_certificate.signature,
|
|
0,
|
|
AVB_RSA4096_NUM_BYTES);
|
|
ScopedRSA key(kPIKPrivateKeyPath);
|
|
ASSERT_TRUE(
|
|
key.Sign(&unlock_credential_.product_unlock_key_certificate.signed_data,
|
|
sizeof(AvbAtxCertificateSignedData),
|
|
unlock_credential_.product_unlock_key_certificate.signature));
|
|
}
|
|
|
|
void SignUnlockCredentialChallenge(const char* key_path) {
|
|
memset(unlock_credential_.challenge_signature, 0, AVB_RSA4096_NUM_BYTES);
|
|
ScopedRSA key(key_path);
|
|
ASSERT_TRUE(key.Sign(unlock_challenge_.data(),
|
|
unlock_challenge_.size(),
|
|
unlock_credential_.challenge_signature));
|
|
}
|
|
|
|
bool PrepareUnlockCredential() {
|
|
// Stage a challenge to be remembered as the 'most recent challenge'. Then
|
|
// the next call to unlock with |unlock_credential_| is expected to succeed.
|
|
fake_random_ = unlock_challenge_;
|
|
AvbAtxUnlockChallenge challenge;
|
|
return (AVB_IO_RESULT_OK ==
|
|
avb_atx_generate_unlock_challenge(ops_.avb_atx_ops(), &challenge));
|
|
}
|
|
|
|
AvbAtxPermanentAttributes attributes_;
|
|
AvbAtxPublicKeyMetadata metadata_;
|
|
bool fail_read_permanent_attributes_{false};
|
|
bool fail_read_permanent_attributes_hash_{false};
|
|
bool fail_read_pik_rollback_index_{false};
|
|
bool fail_read_psk_rollback_index_{false};
|
|
bool fail_get_random_{false};
|
|
std::string fake_random_;
|
|
AvbAtxUnlockCredential unlock_credential_;
|
|
std::string unlock_challenge_;
|
|
|
|
private:
|
|
void ReadDefaultData() {
|
|
std::string tmp;
|
|
ASSERT_TRUE(base::ReadFileToString(base::FilePath(kMetadataPath), &tmp));
|
|
ASSERT_EQ(tmp.size(), sizeof(AvbAtxPublicKeyMetadata));
|
|
memcpy(&metadata_, tmp.data(), tmp.size());
|
|
ASSERT_TRUE(
|
|
base::ReadFileToString(base::FilePath(kPermanentAttributesPath), &tmp));
|
|
ASSERT_EQ(tmp.size(), sizeof(AvbAtxPermanentAttributes));
|
|
memcpy(&attributes_, tmp.data(), tmp.size());
|
|
ASSERT_TRUE(base::ReadFileToString(base::FilePath(kUnlockChallengePath),
|
|
&unlock_challenge_));
|
|
ASSERT_EQ(size_t(AVB_ATX_UNLOCK_CHALLENGE_SIZE), unlock_challenge_.size());
|
|
ASSERT_TRUE(
|
|
base::ReadFileToString(base::FilePath(kUnlockCredentialPath), &tmp));
|
|
ASSERT_EQ(tmp.size(), sizeof(AvbAtxUnlockCredential));
|
|
memcpy(&unlock_credential_, tmp.data(), tmp.size());
|
|
}
|
|
};
|
|
|
|
TEST_F(AvbAtxValidateTest, Success) {
|
|
bool is_trusted = false;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
|
|
// Check that the key versions were reported correctly.
|
|
EXPECT_EQ(
|
|
ops_.get_verified_rollback_indexes()[AVB_ATX_PIK_VERSION_LOCATION],
|
|
metadata_.product_intermediate_key_certificate.signed_data.key_version);
|
|
EXPECT_EQ(ops_.get_verified_rollback_indexes()[AVB_ATX_PSK_VERSION_LOCATION],
|
|
metadata_.product_signing_key_certificate.signed_data.key_version);
|
|
EXPECT_EQ(2UL, ops_.get_verified_rollback_indexes().size());
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, SuccessAfterNewSign) {
|
|
std::string old_pik_sig(
|
|
reinterpret_cast<char*>(
|
|
metadata_.product_intermediate_key_certificate.signature),
|
|
AVB_RSA4096_NUM_BYTES);
|
|
std::string old_psk_sig(
|
|
reinterpret_cast<char*>(
|
|
metadata_.product_signing_key_certificate.signature),
|
|
AVB_RSA4096_NUM_BYTES);
|
|
SignPIKCertificate();
|
|
SignPSKCertificate();
|
|
std::string new_pik_sig(
|
|
reinterpret_cast<char*>(
|
|
metadata_.product_intermediate_key_certificate.signature),
|
|
AVB_RSA4096_NUM_BYTES);
|
|
std::string new_psk_sig(
|
|
reinterpret_cast<char*>(
|
|
metadata_.product_signing_key_certificate.signature),
|
|
AVB_RSA4096_NUM_BYTES);
|
|
EXPECT_EQ(old_pik_sig, new_pik_sig);
|
|
EXPECT_EQ(old_psk_sig, new_psk_sig);
|
|
bool is_trusted = false;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, FailReadPermamentAttributes) {
|
|
fail_read_permanent_attributes_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, FailReadPermamentAttributesHash) {
|
|
fail_read_permanent_attributes_hash_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, UnsupportedPermanentAttributesVersion) {
|
|
attributes_.version = 25;
|
|
ops_.set_permanent_attributes(attributes_);
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PermanentAttributesHashMismatch) {
|
|
ops_.set_permanent_attributes_hash("bad_hash");
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
// A fixture with parameterized metadata length.
|
|
class AvbAtxValidateTestWithMetadataLength
|
|
: public AvbAtxValidateTest,
|
|
public ::testing::WithParamInterface<size_t> {
|
|
protected:
|
|
AvbIOResult Validate(bool* is_trusted) override {
|
|
return avb_atx_validate_vbmeta_public_key(
|
|
ops_.avb_ops(),
|
|
metadata_.product_signing_key_certificate.signed_data.public_key,
|
|
AVB_ATX_PUBLIC_KEY_SIZE,
|
|
reinterpret_cast<const uint8_t*>(&metadata_),
|
|
GetParam(),
|
|
is_trusted);
|
|
}
|
|
};
|
|
|
|
TEST_P(AvbAtxValidateTestWithMetadataLength, InvalidMetadataLength) {
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
// Test a bunch of invalid metadata length values.
|
|
INSTANTIATE_TEST_CASE_P(P,
|
|
AvbAtxValidateTestWithMetadataLength,
|
|
::testing::Values(0,
|
|
1,
|
|
sizeof(AvbAtxPublicKeyMetadata) - 1,
|
|
sizeof(AvbAtxPublicKeyMetadata) + 1,
|
|
-1));
|
|
|
|
TEST_F(AvbAtxValidateTest, UnsupportedMetadataVersion) {
|
|
metadata_.version = 25;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, FailReadPIKRollbackIndex) {
|
|
fail_read_pik_rollback_index_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, UnsupportedPIKCertificateVersion) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.version = 25;
|
|
SignPIKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPIKCert_ModifiedSubjectPublicKey) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.public_key[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPIKCert_ModifiedSubject) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.subject[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPIKCert_ModifiedUsage) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.usage[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPIKCert_ModifiedKeyVersion) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.key_version ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPIKCert_BadSignature) {
|
|
metadata_.product_intermediate_key_certificate.signature[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PIKCertSubjectIgnored) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.subject[0] ^= 1;
|
|
SignPIKCertificate();
|
|
bool is_trusted = false;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PIKCertUnexpectedUsage) {
|
|
metadata_.product_intermediate_key_certificate.signed_data.usage[0] ^= 1;
|
|
SignPIKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PIKRollback) {
|
|
ops_.set_stored_rollback_indexes(
|
|
{{AVB_ATX_PIK_VERSION_LOCATION,
|
|
metadata_.product_intermediate_key_certificate.signed_data.key_version +
|
|
1},
|
|
{AVB_ATX_PSK_VERSION_LOCATION, 0}});
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, FailReadPSKRollbackIndex) {
|
|
fail_read_psk_rollback_index_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, UnsupportedPSKCertificateVersion) {
|
|
metadata_.product_signing_key_certificate.signed_data.version = 25;
|
|
SignPSKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPSKCert_ModifiedSubjectPublicKey) {
|
|
metadata_.product_signing_key_certificate.signed_data.public_key[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPSKCert_ModifiedSubject) {
|
|
metadata_.product_signing_key_certificate.signed_data.subject[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPSKCert_ModifiedUsage) {
|
|
metadata_.product_signing_key_certificate.signed_data.usage[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPSKCert_ModifiedKeyVersion) {
|
|
metadata_.product_signing_key_certificate.signed_data.key_version ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, BadPSKCert_BadSignature) {
|
|
metadata_.product_signing_key_certificate.signature[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PSKCertUnexpectedSubject) {
|
|
metadata_.product_signing_key_certificate.signed_data.subject[0] ^= 1;
|
|
SignPSKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PSKCertUnexpectedUsage) {
|
|
metadata_.product_signing_key_certificate.signed_data.usage[0] ^= 1;
|
|
SignPSKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, PSKRollback) {
|
|
ops_.set_stored_rollback_indexes(
|
|
{{AVB_ATX_PIK_VERSION_LOCATION, 0},
|
|
{AVB_ATX_PSK_VERSION_LOCATION,
|
|
metadata_.product_signing_key_certificate.signed_data.key_version +
|
|
1}});
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
// A fixture with parameterized public key length.
|
|
class AvbAtxValidateTestWithPublicKeyLength
|
|
: public AvbAtxValidateTest,
|
|
public ::testing::WithParamInterface<size_t> {
|
|
protected:
|
|
AvbIOResult Validate(bool* is_trusted) override {
|
|
return avb_atx_validate_vbmeta_public_key(
|
|
ops_.avb_ops(),
|
|
metadata_.product_signing_key_certificate.signed_data.public_key,
|
|
GetParam(),
|
|
reinterpret_cast<const uint8_t*>(&metadata_),
|
|
sizeof(metadata_),
|
|
is_trusted);
|
|
}
|
|
};
|
|
|
|
TEST_P(AvbAtxValidateTestWithPublicKeyLength, InvalidPublicKeyLength) {
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
// Test a bunch of invalid public key length values.
|
|
INSTANTIATE_TEST_CASE_P(P,
|
|
AvbAtxValidateTestWithPublicKeyLength,
|
|
::testing::Values(0,
|
|
1,
|
|
AVB_ATX_PUBLIC_KEY_SIZE - 1,
|
|
AVB_ATX_PUBLIC_KEY_SIZE + 1,
|
|
AVB_ATX_PUBLIC_KEY_SIZE - 512,
|
|
-1));
|
|
|
|
TEST_F(AvbAtxValidateTest, PSKMismatch) {
|
|
uint8_t bad_key[AVB_ATX_PUBLIC_KEY_SIZE] = {};
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK,
|
|
avb_atx_validate_vbmeta_public_key(
|
|
ops_.avb_ops(),
|
|
bad_key,
|
|
AVB_ATX_PUBLIC_KEY_SIZE,
|
|
reinterpret_cast<const uint8_t*>(&metadata_),
|
|
sizeof(metadata_),
|
|
&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, GenerateUnlockChallenge) {
|
|
fake_random_ = std::string(AVB_ATX_UNLOCK_CHALLENGE_SIZE, 'C');
|
|
AvbAtxUnlockChallenge challenge;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK,
|
|
avb_atx_generate_unlock_challenge(ops_.avb_atx_ops(), &challenge));
|
|
EXPECT_EQ(1UL, challenge.version);
|
|
EXPECT_EQ(0,
|
|
memcmp(fake_random_.data(),
|
|
challenge.challenge,
|
|
AVB_ATX_UNLOCK_CHALLENGE_SIZE));
|
|
uint8_t expected_pid_hash[AVB_SHA256_DIGEST_SIZE];
|
|
SHA256(attributes_.product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_pid_hash);
|
|
EXPECT_EQ(0,
|
|
memcmp(expected_pid_hash,
|
|
challenge.product_id_hash,
|
|
AVB_SHA256_DIGEST_SIZE));
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, GenerateUnlockChallenge_NoAttributes) {
|
|
fail_read_permanent_attributes_ = true;
|
|
AvbAtxUnlockChallenge challenge;
|
|
EXPECT_NE(AVB_IO_RESULT_OK,
|
|
avb_atx_generate_unlock_challenge(ops_.avb_atx_ops(), &challenge));
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, GenerateUnlockChallenge_NoRNG) {
|
|
fail_get_random_ = true;
|
|
AvbAtxUnlockChallenge challenge;
|
|
EXPECT_NE(AVB_IO_RESULT_OK,
|
|
avb_atx_generate_unlock_challenge(ops_.avb_atx_ops(), &challenge));
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_UnsupportedVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.version++;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_NoAttributes) {
|
|
PrepareUnlockCredential();
|
|
fail_read_permanent_attributes_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_NoAttributesHash) {
|
|
PrepareUnlockCredential();
|
|
fail_read_permanent_attributes_hash_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_UnsupportedAttributesVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
attributes_.version = 25;
|
|
ops_.set_permanent_attributes(attributes_);
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_AttributesHashMismatch) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
ops_.set_permanent_attributes_hash("bad_hash");
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_FailReadPIKRollbackIndex) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
fail_read_pik_rollback_index_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_UnsupportedPIKCertificateVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data.version =
|
|
25;
|
|
SignUnlockCredentialPIKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPIKCert_ModifiedSubjectPublicKey) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.public_key[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPIKCert_ModifiedSubject) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.subject[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_BadPIKCert_ModifiedUsage) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.usage[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPIKCert_ModifiedKeyVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.key_version ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_BadPIKCert_BadSignature) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signature[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PIKCertSubjectIgnored) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.subject[0] ^= 1;
|
|
SignUnlockCredentialPIKCertificate();
|
|
bool is_trusted = false;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PIKCertUnexpectedUsage) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.usage[0] ^= 1;
|
|
SignUnlockCredentialPIKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PIKRollback) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
ops_.set_stored_rollback_indexes(
|
|
{{AVB_ATX_PIK_VERSION_LOCATION,
|
|
unlock_credential_.product_intermediate_key_certificate.signed_data
|
|
.key_version +
|
|
1},
|
|
{AVB_ATX_PSK_VERSION_LOCATION, 0}});
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_FailReadPSKRollbackIndex) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
fail_read_psk_rollback_index_ = true;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_UnsupportedPUKCertificateVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.version = 25;
|
|
SignUnlockCredentialPUKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPUKCert_ModifiedSubjectPublicKey) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.public_key[0] ^=
|
|
1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPUKCert_ModifiedSubject) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.subject[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_BadPUKCert_ModifiedUsage) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.usage[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest,
|
|
ValidateUnlockCredential_BadPUKCert_ModifiedKeyVersion) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.key_version ^=
|
|
1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_BadPUKCert_BadSignature) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signature[0] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PUKCertUnexpectedSubject) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.subject[0] ^= 1;
|
|
SignUnlockCredentialPUKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PUKCertUnexpectedUsage) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.product_unlock_key_certificate.signed_data.usage[0] ^= 1;
|
|
SignUnlockCredentialPUKCertificate();
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_PUKRollback) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
ops_.set_stored_rollback_indexes(
|
|
{{AVB_ATX_PIK_VERSION_LOCATION, 0},
|
|
{AVB_ATX_PSK_VERSION_LOCATION,
|
|
unlock_credential_.product_unlock_key_certificate.signed_data
|
|
.key_version +
|
|
1}});
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_BadChallengeSignature) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_credential_.challenge_signature[10] ^= 1;
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_ChallengeMismatch) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
unlock_challenge_ = "bad";
|
|
SignUnlockCredentialChallenge(kPUKPrivateKeyPath);
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_UnlockWithPSK) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
// Copy the PSK cert as the PUK cert.
|
|
memcpy(&unlock_credential_.product_unlock_key_certificate,
|
|
&metadata_.product_signing_key_certificate,
|
|
sizeof(AvbAtxCertificate));
|
|
// Sign the challenge with the PSK instead of the PUK.
|
|
SignUnlockCredentialChallenge(kPSKPrivateKeyPath);
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_ReplayChallenge) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
// A second attempt with the same challenge should fail.
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_FALSE(is_trusted);
|
|
}
|
|
|
|
TEST_F(AvbAtxValidateTest, ValidateUnlockCredential_MultipleUnlock) {
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
bool is_trusted = true;
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
// A second attempt with a newly staged challenge should succeed.
|
|
ASSERT_TRUE(PrepareUnlockCredential());
|
|
EXPECT_EQ(AVB_IO_RESULT_OK, ValidateUnlock(&is_trusted));
|
|
EXPECT_TRUE(is_trusted);
|
|
}
|
|
|
|
// A fixture for testing avb_slot_verify() with ATX.
|
|
class AvbAtxSlotVerifyTest : public BaseAvbToolTest,
|
|
public FakeAvbOpsDelegateWithDefaults {
|
|
public:
|
|
~AvbAtxSlotVerifyTest() 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_rollback_indexes({{0, 0},
|
|
{1, 0},
|
|
{2, 0},
|
|
{3, 0},
|
|
{AVB_ATX_PIK_VERSION_LOCATION, 0},
|
|
{AVB_ATX_PSK_VERSION_LOCATION, 0}});
|
|
ops_.set_stored_is_device_unlocked(false);
|
|
}
|
|
|
|
// FakeAvbOpsDelegate override.
|
|
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_.avb_ops(),
|
|
public_key_data,
|
|
public_key_length,
|
|
public_key_metadata,
|
|
public_key_metadata_length,
|
|
out_key_is_trusted);
|
|
}
|
|
|
|
protected:
|
|
AvbAtxPermanentAttributes attributes_;
|
|
int num_atx_calls_ = 0;
|
|
|
|
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_F(AvbAtxSlotVerifyTest, SlotVerifyWithAtx) {
|
|
std::string metadata_option = "--public_key_metadata=";
|
|
metadata_option += kMetadataPath;
|
|
GenerateVBMetaImage("vbmeta_a.img",
|
|
"SHA512_RSA4096",
|
|
0,
|
|
base::FilePath("test/data/testkey_atx_psk.pem"),
|
|
metadata_option);
|
|
|
|
ops_.set_expected_public_key(
|
|
PublicKeyAVB(base::FilePath("test/data/testkey_atx_psk.pem")));
|
|
|
|
AvbSlotVerifyData* slot_data = NULL;
|
|
const char* requested_partitions[] = {"boot", NULL};
|
|
EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
|
|
avb_slot_verify(ops_.avb_ops(),
|
|
requested_partitions,
|
|
"_a",
|
|
AVB_SLOT_VERIFY_FLAGS_NONE,
|
|
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
|
|
&slot_data));
|
|
EXPECT_NE(nullptr, slot_data);
|
|
avb_slot_verify_data_free(slot_data);
|
|
EXPECT_EQ(1, num_atx_calls_);
|
|
}
|
|
|
|
} // namespace avb
|