blob: c228ef709d567b806467b8108ab8212dd9cafbb6 [file] [log] [blame]
Shawn Willden3d943322018-01-02 18:55:47 -07001/*
2 * Copyright (C) 2017 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 "KeymasterHidlTest.h"
18
19namespace android {
20namespace hardware {
21namespace keymaster {
22namespace V4_0 {
23namespace test {
24
25/**
26 * HmacKeySharingTest extends KeymasterHidlTest with some utilities that make writing HMAC sharing
27 * tests easier.
28 */
29class HmacKeySharingTest : public KeymasterHidlTest {
30 protected:
31 struct GetParamsResult {
32 ErrorCode error;
33 HmacSharingParameters params;
34 auto tie() { return std::tie(error, params); }
35 };
36
37 struct ComputeHmacResult {
38 ErrorCode error;
39 HidlBuf sharing_check;
40 auto tie() { return std::tie(error, sharing_check); }
41 };
42
43 using KeymasterVec = std::vector<sp<IKeymasterDevice>>;
44 using ByteString = std::basic_string<uint8_t>;
45 // using NonceVec = std::vector<HidlBuf>;
46
47 GetParamsResult getHmacSharingParameters(IKeymasterDevice& keymaster) {
48 GetParamsResult result;
49 EXPECT_TRUE(keymaster
50 .getHmacSharingParameters([&](auto error, auto params) {
51 result.tie() = std::tie(error, params);
52 })
53 .isOk());
54 return result;
55 }
56
57 hidl_vec<HmacSharingParameters> getHmacSharingParameters(const KeymasterVec& keymasters) {
58 std::vector<HmacSharingParameters> paramsVec;
59 for (auto& keymaster : keymasters) {
60 auto result = getHmacSharingParameters(*keymaster);
61 EXPECT_EQ(ErrorCode::OK, result.error);
62 if (result.error == ErrorCode::OK) paramsVec.push_back(std::move(result.params));
63 }
64 return paramsVec;
65 }
66
67 ComputeHmacResult computeSharedHmac(IKeymasterDevice& keymaster,
68 const hidl_vec<HmacSharingParameters>& params) {
69 ComputeHmacResult result;
70 EXPECT_TRUE(keymaster
71 .computeSharedHmac(params,
72 [&](auto error, auto params) {
73 result.tie() = std::tie(error, params);
74 })
75 .isOk());
76 return result;
77 }
78
79 std::vector<ComputeHmacResult> computeSharedHmac(
80 const KeymasterVec& keymasters, const hidl_vec<HmacSharingParameters>& paramsVec) {
81 std::vector<ComputeHmacResult> resultVec;
82 for (auto& keymaster : keymasters) {
83 resultVec.push_back(computeSharedHmac(*keymaster, paramsVec));
84 }
85 return resultVec;
86 }
87
88 std::vector<ByteString> copyNonces(const hidl_vec<HmacSharingParameters>& paramsVec) {
89 std::vector<ByteString> nonces;
90 for (auto& param : paramsVec) {
91 nonces.emplace_back(param.nonce.data(), param.nonce.size());
92 }
93 return nonces;
94 }
95
96 void verifyResponses(const HidlBuf& expected, const std::vector<ComputeHmacResult>& responses) {
97 for (auto& response : responses) {
98 EXPECT_EQ(ErrorCode::OK, response.error);
99 EXPECT_EQ(expected, response.sharing_check) << "Sharing check values should match.";
100 }
101 }
102};
103
Dan Shi3bacd7f2019-12-10 15:41:18 -0800104TEST_P(HmacKeySharingTest, GetParameters) {
Shawn Willden3d943322018-01-02 18:55:47 -0700105 auto result1 = getHmacSharingParameters(keymaster());
106 EXPECT_EQ(ErrorCode::OK, result1.error);
107
108 auto result2 = getHmacSharingParameters(keymaster());
109 EXPECT_EQ(ErrorCode::OK, result2.error);
110
111 ASSERT_EQ(result1.params.seed, result2.params.seed)
112 << "A given keymaster should always return the same seed.";
113 ASSERT_EQ(result1.params.nonce, result2.params.nonce)
114 << "A given keymaster should always return the same nonce until restart.";
115}
116
Dan Shi3bacd7f2019-12-10 15:41:18 -0800117TEST_P(HmacKeySharingTest, ComputeSharedHmac) {
Shawn Willden3d943322018-01-02 18:55:47 -0700118 auto params = getHmacSharingParameters(all_keymasters());
119 ASSERT_EQ(all_keymasters().size(), params.size())
120 << "One or more keymasters failed to provide parameters.";
121
122 auto nonces = copyNonces(params);
123 EXPECT_EQ(all_keymasters().size(), nonces.size());
124 std::sort(nonces.begin(), nonces.end());
125 std::unique(nonces.begin(), nonces.end());
126 EXPECT_EQ(all_keymasters().size(), nonces.size());
127
128 auto responses = computeSharedHmac(all_keymasters(), params);
129 ASSERT_GT(responses.size(), 0U);
130 verifyResponses(responses[0].sharing_check, responses);
131
132 // Do it a second time. Should get the same answers.
133 params = getHmacSharingParameters(all_keymasters());
134 ASSERT_EQ(all_keymasters().size(), params.size())
135 << "One or more keymasters failed to provide parameters.";
136
137 responses = computeSharedHmac(all_keymasters(), params);
138 ASSERT_GT(responses.size(), 0U);
Shawn Willden86a33ac2018-03-29 20:57:01 -0600139 ASSERT_EQ(32U, responses[0].sharing_check.size());
Shawn Willden3d943322018-01-02 18:55:47 -0700140 verifyResponses(responses[0].sharing_check, responses);
141}
142
143template <class F>
144class final_action {
145 public:
Dan Shi3bacd7f2019-12-10 15:41:18 -0800146 explicit final_action(F f) : f_(std::move(f)) {}
147 ~final_action() { f_(); }
Shawn Willden3d943322018-01-02 18:55:47 -0700148
149 private:
150 F f_;
151};
152
153template <class F>
154inline final_action<F> finally(const F& f) {
155 return final_action<F>(f);
156}
157
Dan Shi3bacd7f2019-12-10 15:41:18 -0800158TEST_P(HmacKeySharingTest, ComputeSharedHmacCorruptNonce) {
Shawn Willden3d943322018-01-02 18:55:47 -0700159 // Important: The execution of this test gets the keymaster implementations on the device out of
160 // sync with respect to the HMAC key. Granted that VTS tests aren't run on in-use production
161 // devices, this still has the potential to cause confusion. To mitigate that, we always
162 // (barring crashes :-/) re-run the unmodified agreement process on our way out.
163 auto fixup_hmac = finally(
164 [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
165
166 auto params = getHmacSharingParameters(all_keymasters());
167 ASSERT_EQ(all_keymasters().size(), params.size())
168 << "One or more keymasters failed to provide parameters.";
169
170 // All should be well in the normal case
171 auto responses = computeSharedHmac(all_keymasters(), params);
172
173 ASSERT_GT(responses.size(), 0U);
174 HidlBuf correct_response = responses[0].sharing_check;
175 verifyResponses(correct_response, responses);
176
177 // Pick a random param, a random byte within the param's nonce, and a random bit within
178 // the byte. Flip that bit.
179 size_t param_to_tweak = rand() % params.size();
180 uint8_t byte_to_tweak = rand() % sizeof(params[param_to_tweak].nonce);
181 uint8_t bit_to_tweak = rand() % 8;
182 params[param_to_tweak].nonce[byte_to_tweak] ^= (1 << bit_to_tweak);
183
184 responses = computeSharedHmac(all_keymasters(), params);
185 for (size_t i = 0; i < responses.size(); ++i) {
186 if (i == param_to_tweak) {
187 EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
188 << "Keymaster that provided tweaked param should fail to compute HMAC key";
189 } else {
190 EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
191 EXPECT_NE(correct_response, responses[i].sharing_check)
192 << "Others should calculate a different HMAC key, due to the tweaked nonce.";
193 }
194 }
195}
196
Dan Shi3bacd7f2019-12-10 15:41:18 -0800197TEST_P(HmacKeySharingTest, ComputeSharedHmacCorruptSeed) {
Shawn Willden3d943322018-01-02 18:55:47 -0700198 // Important: The execution of this test gets the keymaster implementations on the device out of
199 // sync with respect to the HMAC key. Granted that VTS tests aren't run on in-use production
200 // devices, this still has the potential to cause confusion. To mitigate that, we always
201 // (barring crashes :-/) re-run the unmodified agreement process on our way out.
202 auto fixup_hmac = finally(
203 [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
204
205 auto params = getHmacSharingParameters(all_keymasters());
206 ASSERT_EQ(all_keymasters().size(), params.size())
207 << "One or more keymasters failed to provide parameters.";
208
209 // All should be well in the normal case
210 auto responses = computeSharedHmac(all_keymasters(), params);
211
212 ASSERT_GT(responses.size(), 0U);
213 HidlBuf correct_response = responses[0].sharing_check;
214 verifyResponses(correct_response, responses);
215
216 // Pick a random param and modify the seed. We just increase the seed length by 1. It doesn't
217 // matter what value is in the additional byte; it changes the seed regardless.
218 auto param_to_tweak = rand() % params.size();
219 auto& to_tweak = params[param_to_tweak].seed;
Shawn Willden86a33ac2018-03-29 20:57:01 -0600220 ASSERT_TRUE(to_tweak.size() == 32 || to_tweak.size() == 0);
221 if (!to_tweak.size()) {
222 to_tweak.resize(32); // Contents don't matter; a little randomization is nice.
223 }
224 to_tweak[0]++;
Shawn Willden3d943322018-01-02 18:55:47 -0700225
226 responses = computeSharedHmac(all_keymasters(), params);
227 for (size_t i = 0; i < responses.size(); ++i) {
228 if (i == param_to_tweak) {
229 EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
230 << "Keymaster that provided tweaked param should fail to compute HMAC key ";
231 } else {
232 EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
233 EXPECT_NE(correct_response, responses[i].sharing_check)
234 << "Others should calculate a different HMAC key, due to the tweaked nonce.";
235 }
236 }
237}
238
Dan Shi3bacd7f2019-12-10 15:41:18 -0800239INSTANTIATE_TEST_SUITE_P(
240 PerInstance, HmacKeySharingTest,
241 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor)),
242 android::hardware::PrintInstanceNameToString);
243
Shawn Willden3d943322018-01-02 18:55:47 -0700244} // namespace test
245} // namespace V4_0
246} // namespace keymaster
247} // namespace hardware
248} // namespace android