1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include "examples/cert/avb_cert_slot_verify.h"
26
27 #include <base/files/file_util.h>
28 #include <gtest/gtest.h>
29 #include <openssl/sha.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "avb_unittest_util.h"
34 #include "fake_avb_ops.h"
35
36 namespace {
37
38 const char kMetadataPath[] = "test/data/cert_metadata.bin";
39 const char kPermanentAttributesPath[] =
40 "test/data/cert_permanent_attributes.bin";
41 const uint64_t kNewRollbackValue = 42;
42
43 } /* namespace */
44
45 namespace avb {
46
47 // A fixture for testing avb_cert_slot_verify() with libavb_cert. This test is
48 // parameterized on the initial stored rollback index (same value used in all
49 // relevant locations).
50 class AvbCertSlotVerifyExampleTest
51 : public BaseAvbToolTest,
52 public FakeAvbOpsDelegateWithDefaults,
53 public ::testing::WithParamInterface<uint64_t> {
54 public:
55 ~AvbCertSlotVerifyExampleTest() override = default;
56
SetUp()57 void SetUp() override {
58 BaseAvbToolTest::SetUp();
59 ReadCertDefaultData();
60 ops_.set_partition_dir(testdir_);
61 ops_.set_delegate(this);
62 ops_.set_permanent_attributes(attributes_);
63 ops_.set_stored_is_device_unlocked(false);
64 }
65
66 // FakeAvbOpsDelegate overrides.
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)67 AvbIOResult validate_vbmeta_public_key(AvbOps* ops,
68 const uint8_t* public_key_data,
69 size_t public_key_length,
70 const uint8_t* public_key_metadata,
71 size_t public_key_metadata_length,
72 bool* out_key_is_trusted) override {
73 // Send to libavb_cert implementation.
74 ++num_cert_calls_;
75 return avb_cert_validate_vbmeta_public_key(ops,
76 public_key_data,
77 public_key_length,
78 public_key_metadata,
79 public_key_metadata_length,
80 out_key_is_trusted);
81 }
82
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,uint64_t rollback_index)83 AvbIOResult write_rollback_index(AvbOps* ops,
84 size_t rollback_index_slot,
85 uint64_t rollback_index) override {
86 num_write_rollback_calls_++;
87 return ops_.write_rollback_index(ops, rollback_index_slot, rollback_index);
88 }
89
set_key_version(size_t rollback_index_location,uint64_t key_version)90 void set_key_version(size_t rollback_index_location,
91 uint64_t key_version) override {
92 num_key_version_calls_++;
93 return ops_.set_key_version(rollback_index_location, key_version);
94 }
95
get_random(size_t num_bytes,uint8_t * output)96 AvbIOResult get_random(size_t num_bytes, uint8_t* output) override {
97 return ops_.get_random(num_bytes, output);
98 }
99
RunSlotVerify()100 void RunSlotVerify() {
101 ops_.set_stored_rollback_indexes(
102 {{0, initial_rollback_value_},
103 {AVB_CERT_PIK_VERSION_LOCATION, initial_rollback_value_},
104 {AVB_CERT_PSK_VERSION_LOCATION, initial_rollback_value_}});
105 std::string metadata_option = "--public_key_metadata=";
106 metadata_option += kMetadataPath;
107 GenerateVBMetaImage("vbmeta_a.img",
108 "SHA512_RSA4096",
109 kNewRollbackValue,
110 "test/data/testkey_cert_psk.pem",
111 metadata_option);
112 SHA256(vbmeta_image_.data(), vbmeta_image_.size(), expected_vbh_extension_);
113
114 ops_.set_expected_public_key(
115 PublicKeyAVB("test/data/testkey_cert_psk.pem"));
116
117 AvbSlotVerifyData* slot_data = NULL;
118 EXPECT_EQ(expected_result_,
119 avb_cert_slot_verify(ops_.avb_cert_ops(),
120 "_a",
121 lock_state_,
122 slot_state_,
123 oem_data_state_,
124 &slot_data,
125 actual_vbh_extension_));
126 if (expected_result_ == AVB_SLOT_VERIFY_RESULT_OK) {
127 EXPECT_NE(nullptr, slot_data);
128 avb_slot_verify_data_free(slot_data);
129 // Make sure libavb_cert is being run.
130 EXPECT_EQ(1, num_cert_calls_);
131 // Make sure we're hooking set_key_version.
132 EXPECT_EQ(0, num_key_version_calls_);
133 }
134 }
135
CheckVBH()136 void CheckVBH() {
137 if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
138 lock_state_ == AVB_CERT_UNLOCKED) {
139 memset(&expected_vbh_extension_, 0, AVB_SHA256_DIGEST_SIZE);
140 }
141 // Check that the VBH was correctly calculated.
142 EXPECT_EQ(0,
143 memcmp(actual_vbh_extension_,
144 expected_vbh_extension_,
145 AVB_SHA256_DIGEST_SIZE));
146 }
147
CheckNewRollbackState()148 void CheckNewRollbackState() {
149 uint64_t expected_rollback_value = kNewRollbackValue;
150 if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
151 lock_state_ == AVB_CERT_UNLOCKED ||
152 slot_state_ != AVB_CERT_SLOT_MARKED_SUCCESSFUL) {
153 // Check that rollback indexes were unmodified.
154 expected_rollback_value = initial_rollback_value_;
155 }
156 // Check that all rollback indexes have the expected value.
157 std::map<size_t, uint64_t> stored_rollback_indexes =
158 ops_.get_stored_rollback_indexes();
159 EXPECT_EQ(expected_rollback_value, stored_rollback_indexes[0]);
160 EXPECT_EQ(expected_rollback_value,
161 stored_rollback_indexes[AVB_CERT_PIK_VERSION_LOCATION]);
162 EXPECT_EQ(expected_rollback_value,
163 stored_rollback_indexes[AVB_CERT_PSK_VERSION_LOCATION]);
164 // Check that if the rollback did not need to change, there were no writes.
165 if (initial_rollback_value_ == kNewRollbackValue ||
166 initial_rollback_value_ == expected_rollback_value) {
167 EXPECT_EQ(0, num_write_rollback_calls_);
168 } else {
169 EXPECT_NE(0, num_write_rollback_calls_);
170 }
171 }
172
173 protected:
174 AvbCertPermanentAttributes attributes_;
175 int num_cert_calls_ = 0;
176 int num_key_version_calls_ = 0;
177 int num_write_rollback_calls_ = 0;
178 AvbSlotVerifyResult expected_result_ = AVB_SLOT_VERIFY_RESULT_OK;
179 uint64_t initial_rollback_value_ = 0;
180 AvbCertLockState lock_state_ = AVB_CERT_LOCKED;
181 AvbCertSlotState slot_state_ = AVB_CERT_SLOT_MARKED_SUCCESSFUL;
182 AvbCertOemDataState oem_data_state_ = AVB_CERT_OEM_DATA_NOT_USED;
183 uint8_t expected_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
184 uint8_t actual_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
185
186 private:
ReadCertDefaultData()187 void ReadCertDefaultData() {
188 std::string tmp;
189 ASSERT_TRUE(
190 base::ReadFileToString(base::FilePath(kPermanentAttributesPath), &tmp));
191 ASSERT_EQ(tmp.size(), sizeof(AvbCertPermanentAttributes));
192 memcpy(&attributes_, tmp.data(), tmp.size());
193 }
194 };
195
TEST_P(AvbCertSlotVerifyExampleTest,RunWithStartingIndex)196 TEST_P(AvbCertSlotVerifyExampleTest, RunWithStartingIndex) {
197 initial_rollback_value_ = GetParam();
198 RunSlotVerify();
199 CheckVBH();
200 CheckNewRollbackState();
201 }
202
203 INSTANTIATE_TEST_CASE_P(P,
204 AvbCertSlotVerifyExampleTest,
205 ::testing::Values(0,
206 1,
207 kNewRollbackValue / 2,
208 kNewRollbackValue - 1,
209 kNewRollbackValue));
210
TEST_F(AvbCertSlotVerifyExampleTest,RunUnlocked)211 TEST_F(AvbCertSlotVerifyExampleTest, RunUnlocked) {
212 lock_state_ = AVB_CERT_UNLOCKED;
213 RunSlotVerify();
214 CheckVBH();
215 CheckNewRollbackState();
216 }
217
TEST_F(AvbCertSlotVerifyExampleTest,RunWithSlotNotMarkedSuccessful)218 TEST_F(AvbCertSlotVerifyExampleTest, RunWithSlotNotMarkedSuccessful) {
219 slot_state_ = AVB_CERT_SLOT_NOT_MARKED_SUCCESSFUL;
220 RunSlotVerify();
221 CheckVBH();
222 CheckNewRollbackState();
223 }
224
TEST_F(AvbCertSlotVerifyExampleTest,RunWithOemData)225 TEST_F(AvbCertSlotVerifyExampleTest, RunWithOemData) {
226 oem_data_state_ = AVB_CERT_OEM_DATA_USED;
227 RunSlotVerify();
228 CheckVBH();
229 CheckNewRollbackState();
230 }
231
232 } // namespace avb
233