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 <stdio.h>
26 #include <string.h>
27 
28 #include <base/files/file_util.h>
29 #include <gtest/gtest.h>
30 #include <openssl/sha.h>
31 
32 #include "avb_unittest_util.h"
33 #include "examples/things/avb_atx_slot_verify.h"
34 #include "fake_avb_ops.h"
35 
36 namespace {
37 
38 const char kMetadataPath[] = "test/data/atx_metadata.bin";
39 const char kPermanentAttributesPath[] =
40     "test/data/atx_permanent_attributes.bin";
41 const uint64_t kNewRollbackValue = 42;
42 
43 } /* namespace */
44 
45 namespace avb {
46 
47 // A fixture for testing avb_atx_slot_verify() with ATX. This test is
48 // parameterized on the initial stored rollback index (same value used in all
49 // relevant locations).
50 class AvbAtxSlotVerifyExampleTest
51     : public BaseAvbToolTest,
52       public FakeAvbOpsDelegateWithDefaults,
53       public ::testing::WithParamInterface<uint64_t> {
54  public:
55   ~AvbAtxSlotVerifyExampleTest() override = default;
56 
57   void SetUp() override {
58     BaseAvbToolTest::SetUp();
59     ReadAtxDefaultData();
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.
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 ATX implementation.
74     ++num_atx_calls_;
75     return avb_atx_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 
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 
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 
96   void RunSlotVerify() {
97     ops_.set_stored_rollback_indexes(
98         {{0, initial_rollback_value_},
99          {AVB_ATX_PIK_VERSION_LOCATION, initial_rollback_value_},
100          {AVB_ATX_PSK_VERSION_LOCATION, initial_rollback_value_}});
101     std::string metadata_option = "--public_key_metadata=";
102     metadata_option += kMetadataPath;
103     GenerateVBMetaImage("vbmeta_a.img",
104                         "SHA512_RSA4096",
105                         kNewRollbackValue,
106                         base::FilePath("test/data/testkey_atx_psk.pem"),
107                         metadata_option);
108     SHA256(vbmeta_image_.data(), vbmeta_image_.size(), expected_vbh_extension_);
109 
110     ops_.set_expected_public_key(
111         PublicKeyAVB(base::FilePath("test/data/testkey_atx_psk.pem")));
112 
113     AvbSlotVerifyData* slot_data = NULL;
114     EXPECT_EQ(expected_result_,
115               avb_atx_slot_verify(ops_.avb_atx_ops(),
116                                   "_a",
117                                   lock_state_,
118                                   slot_state_,
119                                   oem_data_state_,
120                                   &slot_data,
121                                   actual_vbh_extension_));
122     if (expected_result_ == AVB_SLOT_VERIFY_RESULT_OK) {
123       EXPECT_NE(nullptr, slot_data);
124       avb_slot_verify_data_free(slot_data);
125       // Make sure ATX is being run.
126       EXPECT_EQ(1, num_atx_calls_);
127       // Make sure we're hooking set_key_version.
128       EXPECT_EQ(0, num_key_version_calls_);
129     }
130   }
131 
132   void CheckVBH() {
133     if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
134         lock_state_ == AVB_ATX_UNLOCKED) {
135       memset(&expected_vbh_extension_, 0, AVB_SHA256_DIGEST_SIZE);
136     }
137     // Check that the VBH was correctly calculated.
138     EXPECT_EQ(0,
139               memcmp(actual_vbh_extension_,
140                      expected_vbh_extension_,
141                      AVB_SHA256_DIGEST_SIZE));
142   }
143 
144   void CheckNewRollbackState() {
145     uint64_t expected_rollback_value = kNewRollbackValue;
146     if (expected_result_ != AVB_SLOT_VERIFY_RESULT_OK ||
147         lock_state_ == AVB_ATX_UNLOCKED ||
148         slot_state_ != AVB_ATX_SLOT_MARKED_SUCCESSFUL) {
149       // Check that rollback indexes were unmodified.
150       expected_rollback_value = initial_rollback_value_;
151     }
152     // Check that all rollback indexes have the expected value.
153     std::map<size_t, uint64_t> stored_rollback_indexes =
154         ops_.get_stored_rollback_indexes();
155     EXPECT_EQ(expected_rollback_value, stored_rollback_indexes[0]);
156     EXPECT_EQ(expected_rollback_value,
157               stored_rollback_indexes[AVB_ATX_PIK_VERSION_LOCATION]);
158     EXPECT_EQ(expected_rollback_value,
159               stored_rollback_indexes[AVB_ATX_PSK_VERSION_LOCATION]);
160     // Check that if the rollback did not need to change, there were no writes.
161     if (initial_rollback_value_ == kNewRollbackValue ||
162         initial_rollback_value_ == expected_rollback_value) {
163       EXPECT_EQ(0, num_write_rollback_calls_);
164     } else {
165       EXPECT_NE(0, num_write_rollback_calls_);
166     }
167   }
168 
169  protected:
170   AvbAtxPermanentAttributes attributes_;
171   int num_atx_calls_ = 0;
172   int num_key_version_calls_ = 0;
173   int num_write_rollback_calls_ = 0;
174   AvbSlotVerifyResult expected_result_ = AVB_SLOT_VERIFY_RESULT_OK;
175   uint64_t initial_rollback_value_ = 0;
176   AvbAtxLockState lock_state_ = AVB_ATX_LOCKED;
177   AvbAtxSlotState slot_state_ = AVB_ATX_SLOT_MARKED_SUCCESSFUL;
178   AvbAtxOemDataState oem_data_state_ = AVB_ATX_OEM_DATA_NOT_USED;
179   uint8_t expected_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
180   uint8_t actual_vbh_extension_[AVB_SHA256_DIGEST_SIZE] = {};
181 
182  private:
183   void ReadAtxDefaultData() {
184     std::string tmp;
185     ASSERT_TRUE(
186         base::ReadFileToString(base::FilePath(kPermanentAttributesPath), &tmp));
187     ASSERT_EQ(tmp.size(), sizeof(AvbAtxPermanentAttributes));
188     memcpy(&attributes_, tmp.data(), tmp.size());
189   }
190 };
191 
192 TEST_P(AvbAtxSlotVerifyExampleTest, RunWithStartingIndex) {
193   initial_rollback_value_ = GetParam();
194   RunSlotVerify();
195   CheckVBH();
196   CheckNewRollbackState();
197 }
198 
199 INSTANTIATE_TEST_CASE_P(P,
200                         AvbAtxSlotVerifyExampleTest,
201                         ::testing::Values(0,
202                                           1,
203                                           kNewRollbackValue / 2,
204                                           kNewRollbackValue - 1,
205                                           kNewRollbackValue));
206 
207 TEST_F(AvbAtxSlotVerifyExampleTest, RunUnlocked) {
208   lock_state_ = AVB_ATX_UNLOCKED;
209   RunSlotVerify();
210   CheckVBH();
211   CheckNewRollbackState();
212 }
213 
214 TEST_F(AvbAtxSlotVerifyExampleTest, RunWithSlotNotMarkedSuccessful) {
215   slot_state_ = AVB_ATX_SLOT_NOT_MARKED_SUCCESSFUL;
216   RunSlotVerify();
217   CheckVBH();
218   CheckNewRollbackState();
219 }
220 
221 TEST_F(AvbAtxSlotVerifyExampleTest, RunWithOemData) {
222   oem_data_state_ = AVB_ATX_OEM_DATA_USED;
223   RunSlotVerify();
224   CheckVBH();
225   CheckNewRollbackState();
226 }
227 
228 }  // namespace avb
229