1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "VehicleBindingUtil.h"
18 
19 #include <android/hardware/automotive/vehicle/2.0/types.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include <hidl/Status.h>
23 #include <utils/SystemClock.h>
24 
25 #include <AidlHalPropConfig.h>
26 #include <AidlHalPropValue.h>
27 #include <IHalPropConfig.h>
28 #include <IHalPropValue.h>
29 #include <IVhalClient.h>
30 #include <VehicleHalTypes.h>
31 #include <VehicleUtils.h>
32 
33 #include <iterator>
34 
35 namespace android {
36 namespace automotive {
37 namespace security {
38 
39 namespace {
40 
41 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
42 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
43 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
44 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
45 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
46 using ::android::frameworks::automotive::vhal::AidlHalPropConfig;
47 using ::android::frameworks::automotive::vhal::AidlHalPropValue;
48 using ::android::frameworks::automotive::vhal::ClientStatusError;
49 using ::android::frameworks::automotive::vhal::ErrorCode;
50 using ::android::frameworks::automotive::vhal::IHalPropConfig;
51 using ::android::frameworks::automotive::vhal::IHalPropValue;
52 using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
53 using ::android::frameworks::automotive::vhal::ISubscriptionClient;
54 using ::android::frameworks::automotive::vhal::IVhalClient;
55 using ::android::frameworks::automotive::vhal::VhalClientResult;
56 using ::android::hardware::Void;
57 
58 template <typename T>
59 using VhalReturn = android::hardware::Return<T>;
60 
61 using ::testing::_;
62 using ::testing::DoAll;
63 using ::testing::ElementsAreArray;
64 using ::testing::NotNull;
65 using ::testing::Return;
66 using ::testing::SetArgPointee;
67 using ::testing::Test;
68 
69 class MockVehicle : public IVhalClient {
70 public:
isAidlVhal()71     bool isAidlVhal() override { return true; }
72 
73     MOCK_METHOD(std::unique_ptr<IHalPropValue>, createHalPropValue, (int32_t), (override));
74 
75     MOCK_METHOD(std::unique_ptr<IHalPropValue>, createHalPropValue, (int32_t, int32_t), (override));
76 
77     MOCK_METHOD(void, getValue, (const IHalPropValue&, std::shared_ptr<GetValueCallbackFunc>),
78                 (override));
79 
80     MOCK_METHOD(void, setValue, (const IHalPropValue&, std::shared_ptr<SetValueCallbackFunc>),
81                 (override));
82 
83     MOCK_METHOD(VhalClientResult<void>, addOnBinderDiedCallback,
84                 (std::shared_ptr<OnBinderDiedCallbackFunc>), (override));
85 
86     MOCK_METHOD(VhalClientResult<void>, removeOnBinderDiedCallback,
87                 (std::shared_ptr<OnBinderDiedCallbackFunc>), (override));
88 
89     MOCK_METHOD(VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>>, getAllPropConfigs,
90                 (), (override));
91 
92     MOCK_METHOD(VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>>, getPropConfigs,
93                 (std::vector<int32_t>), (override));
94 
95     MOCK_METHOD(std::unique_ptr<ISubscriptionClient>, getSubscriptionClient,
96                 (std::shared_ptr<ISubscriptionCallback>), (override));
97 };
98 
99 class MockCsrng : public Csrng {
100 public:
101     MOCK_METHOD(bool, fill, (void*, size_t), (const override));
102 };
103 
104 class MockExecutor : public Executor {
105 public:
106     MOCK_METHOD(int, run, (const std::vector<std::string>&, int*), (const override));
107 };
108 
109 class VehicleBindingUtilTests : public Test {
110 protected:
SetUp()111     void SetUp() override {
112         ON_CALL(*mMockVehicle, createHalPropValue(_)).WillByDefault([](int32_t propId) {
113             return std::make_unique<AidlHalPropValue>(propId);
114         });
115 
116         ON_CALL(*mMockVehicle, createHalPropValue(_, _))
117                 .WillByDefault([](int32_t propId, int32_t areaId) {
118                     return std::make_unique<AidlHalPropValue>(propId, areaId);
119                 });
120     }
121 
setMockVhalPropertySupported()122     void setMockVhalPropertySupported() {
123         std::vector<int32_t> expectedProps = {
124                 toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED)};
125 
126         EXPECT_CALL(*mMockVehicle, getPropConfigs(expectedProps))
127                 .WillOnce([](const std::vector<int32_t>&) {
128                     std::vector<std::unique_ptr<IHalPropConfig>> configs;
129                     VehiclePropConfig config;
130                     configs.push_back(std::make_unique<AidlHalPropConfig>(std::move(config)));
131                     return std::move(configs);
132                 });
133     }
134 
setMockVhalPropertyValue(const std::vector<uint8_t> & seed)135     void setMockVhalPropertyValue(const std::vector<uint8_t>& seed) {
136         EXPECT_CALL(*mMockVehicle, getValue(_, _))
137                 .WillOnce(
138                         [seed](const IHalPropValue& propValue,
139                                const std::shared_ptr<MockVehicle::GetValueCallbackFunc>& callback) {
140                             EXPECT_EQ(propValue.getPropId(),
141                                       toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED));
142                             std::unique_ptr<IHalPropValue> value =
143                                     std::make_unique<AidlHalPropValue>(propValue.getPropId());
144                             value->setByteValues(seed);
145                             (*callback)(std::move(value));
146                         });
147     }
148 
setTestRandomness(const char seed[SEED_BYTE_SIZE])149     void setTestRandomness(const char seed[SEED_BYTE_SIZE]) {
150         EXPECT_CALL(mMockCsrng, fill(NotNull(), SEED_BYTE_SIZE))
151                 .WillOnce([seed](void* buf, size_t) {
152                     memcpy(buf, seed, SEED_BYTE_SIZE);
153                     return true;
154                 });
155     }
156 
toVector(const char seed[SEED_BYTE_SIZE])157     static std::vector<uint8_t> toVector(const char seed[SEED_BYTE_SIZE]) {
158         return {seed, seed + SEED_BYTE_SIZE};
159     }
160 
makeVdcArgs()161     static std::vector<std::string> makeVdcArgs() {
162         return {"/system/bin/vdc", "cryptfs", "bindkeys"};
163     }
164 
165     std::shared_ptr<MockVehicle> mMockVehicle = std::make_shared<MockVehicle>();
166     MockExecutor mMockExecutor;
167     MockCsrng mMockCsrng;
168 };
169 
170 // Verify that we fail as expected if the VHAL property is not supported. This
171 // is not necessarily an error, and is expected on platforms that don't
172 // implement the feature.
TEST_F(VehicleBindingUtilTests,VhalPropertyUnsupported)173 TEST_F(VehicleBindingUtilTests, VhalPropertyUnsupported) {
174     std::vector<int32_t> expectedProps = {toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED)};
175     EXPECT_CALL(*mMockVehicle, getPropConfigs(expectedProps))
176             .WillOnce([](const std::vector<int32_t>&) {
177                 std::vector<std::unique_ptr<IHalPropConfig>> configs;
178                 return std::move(configs);
179             });
180 
181     EXPECT_EQ(BindingStatus::NOT_SUPPORTED,
182               setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
183 }
184 
185 // Verify that we properly handle an attempt to generate a random seed.
TEST_F(VehicleBindingUtilTests,GetRandomnessFails)186 TEST_F(VehicleBindingUtilTests, GetRandomnessFails) {
187     setMockVhalPropertySupported();
188     setMockVhalPropertyValue({});
189     EXPECT_CALL(mMockCsrng, fill(_, SEED_BYTE_SIZE)).WillOnce(Return(false));
190     EXPECT_EQ(BindingStatus::ERROR, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
191 }
192 
193 // Verify that we properly handle an attempt to generate a random seed.
TEST_F(VehicleBindingUtilTests,GetSeedVhalPropertyFails)194 TEST_F(VehicleBindingUtilTests, GetSeedVhalPropertyFails) {
195     setMockVhalPropertySupported();
196 
197     EXPECT_CALL(*mMockVehicle, getValue(_, _))
198             .WillOnce([](const IHalPropValue& propValue,
199                          const std::shared_ptr<MockVehicle::GetValueCallbackFunc>& callback) {
200                 EXPECT_EQ(propValue.getPropId(),
201                           toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED));
202                 (*callback)(ClientStatusError(StatusCode::NOT_AVAILABLE));
203             });
204     EXPECT_EQ(BindingStatus::ERROR, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
205 }
206 
TEST_F(VehicleBindingUtilTests,SetSeedVhalPropertyFails)207 TEST_F(VehicleBindingUtilTests, SetSeedVhalPropertyFails) {
208     setMockVhalPropertySupported();
209     setMockVhalPropertyValue({});
210     setTestRandomness("I am not random");
211 
212     EXPECT_CALL(*mMockVehicle, setValue(_, _))
213             .WillOnce([](const IHalPropValue&,
214                          const std::shared_ptr<MockVehicle::SetValueCallbackFunc>& callback) {
215                 (*callback)(ClientStatusError(StatusCode::NOT_AVAILABLE));
216             });
217 
218     EXPECT_EQ(BindingStatus::ERROR, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
219 }
220 
TEST_F(VehicleBindingUtilTests,SetSeedWithNewRandomSeed)221 TEST_F(VehicleBindingUtilTests, SetSeedWithNewRandomSeed) {
222     setMockVhalPropertySupported();
223     setMockVhalPropertyValue({});
224     constexpr char SEED[SEED_BYTE_SIZE] = "Seed Value Here";
225     setTestRandomness(SEED);
226 
227     EXPECT_CALL(*mMockVehicle, setValue(_, _))
228             .WillOnce([SEED](const IHalPropValue& value,
229                              const std::shared_ptr<MockVehicle::SetValueCallbackFunc>& callback) {
230                 EXPECT_EQ(value.getPropId(),
231                           toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED));
232                 EXPECT_THAT(value.getByteValues(), testing::ElementsAreArray(SEED));
233                 (*callback)({});
234             });
235 
236     EXPECT_CALL(mMockExecutor, run(ElementsAreArray(makeVdcArgs()), _)).WillOnce(Return(0));
237 
238     EXPECT_EQ(BindingStatus::OK, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
239 }
240 
TEST_F(VehicleBindingUtilTests,SetSeedWithExistingProperty)241 TEST_F(VehicleBindingUtilTests, SetSeedWithExistingProperty) {
242     setMockVhalPropertySupported();
243     const auto SEED = toVector("16 bytes of seed");
244     setMockVhalPropertyValue(SEED);
245     EXPECT_CALL(mMockExecutor, run(ElementsAreArray(makeVdcArgs()), _)).WillOnce(Return(0));
246     EXPECT_EQ(BindingStatus::OK, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
247 }
248 
TEST_F(VehicleBindingUtilTests,SetSeedVdcExecFails)249 TEST_F(VehicleBindingUtilTests, SetSeedVdcExecFails) {
250     setMockVhalPropertySupported();
251     const auto SEED = toVector("abcdefghijklmnop");
252     setMockVhalPropertyValue(SEED);
253     EXPECT_CALL(mMockExecutor, run(ElementsAreArray(makeVdcArgs()), _)).WillOnce(Return(-1));
254     EXPECT_EQ(BindingStatus::ERROR, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
255 }
256 
TEST_F(VehicleBindingUtilTests,SetSeedVdcExitsWithNonZeroStatus)257 TEST_F(VehicleBindingUtilTests, SetSeedVdcExitsWithNonZeroStatus) {
258     setMockVhalPropertySupported();
259     const auto SEED = toVector("1123581321345589");
260     setMockVhalPropertyValue(SEED);
261     EXPECT_CALL(mMockExecutor, run(ElementsAreArray(makeVdcArgs()), _))
262             .WillOnce(DoAll(SetArgPointee<1>(-1), Return(0)));
263     EXPECT_EQ(BindingStatus::ERROR, setVehicleBindingSeed(mMockVehicle, mMockExecutor, mMockCsrng));
264 }
265 
266 }  // namespace
267 }  // namespace security
268 }  // namespace automotive
269 }  // namespace android
270