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