1 /*
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
19 namespace android {
20 namespace hardware {
21 namespace keymaster {
22 namespace V4_0 {
23 namespace test {
24
25 class VerificationTokenTest : public KeymasterHidlTest {
26 protected:
27 struct VerifyAuthorizationResult {
28 bool callSuccessful;
29 ErrorCode error;
30 VerificationToken token;
31 };
32
verifyAuthorization(uint64_t operationHandle,const AuthorizationSet & paramsToVerify,const HardwareAuthToken & authToken)33 VerifyAuthorizationResult verifyAuthorization(uint64_t operationHandle,
34 const AuthorizationSet& paramsToVerify,
35 const HardwareAuthToken& authToken) {
36 VerifyAuthorizationResult result;
37 result.callSuccessful =
38 keymaster()
39 .verifyAuthorization(operationHandle, paramsToVerify.hidl_data(), authToken,
40 [&](auto error, auto token) {
41 result.error = error;
42 result.token = token;
43 })
44 .isOk();
45 return result;
46 }
47
getTime()48 uint64_t getTime() {
49 struct timespec timespec;
50 EXPECT_EQ(0, clock_gettime(CLOCK_BOOTTIME, ×pec));
51 return timespec.tv_sec * 1000 + timespec.tv_nsec / 1000000;
52 }
53
sleep_ms(uint32_t milliseconds)54 int sleep_ms(uint32_t milliseconds) {
55 struct timespec sleep_time = {static_cast<time_t>(milliseconds / 1000),
56 static_cast<long>(milliseconds % 1000) * 1000000};
57 while (sleep_time.tv_sec || sleep_time.tv_nsec) {
58 if (nanosleep(&sleep_time /* to wait */,
59 &sleep_time /* remaining (on interrruption) */) == 0) {
60 sleep_time = {};
61 } else {
62 if (errno != EINTR) return errno;
63 }
64 }
65 return 0;
66 }
67
68 }; // namespace test
69
70 /*
71 * VerificationTokens exist to facilitate cross-Keymaster verification of requirements. As
72 * such, the precise capabilities required will vary depending on the specific vendor
73 * implementations. Essentially, VerificationTokens are a "hook" to enable vendor
74 * implementations to communicate, so the precise usage is defined by those vendors. The only
75 * thing we really can test is that tokens can be created by TEE keymasters, and that the
76 * timestamps increase as expected.
77 */
TEST_P(VerificationTokenTest,TestCreation)78 TEST_P(VerificationTokenTest, TestCreation) {
79 auto result1 = verifyAuthorization(
80 1 /* operation handle */, AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
81 ASSERT_TRUE(result1.callSuccessful);
82 auto result1_time = getTime();
83
84 if (SecLevel() == SecurityLevel::STRONGBOX) {
85 // StrongBox should not implement verifyAuthorization.
86 EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
87 return;
88 }
89
90 EXPECT_EQ(ErrorCode::OK, result1.error);
91 EXPECT_EQ(1U, result1.token.challenge);
92 EXPECT_EQ(SecLevel(), result1.token.securityLevel);
93 EXPECT_EQ(0U, result1.token.parametersVerified.size())
94 << "We didn't supply any parameters to verify";
95 EXPECT_GT(result1.token.timestamp, 0U);
96
97 constexpr uint32_t time_to_sleep = 200;
98 sleep_ms(time_to_sleep);
99
100 auto result2 = verifyAuthorization(
101 2 /* operation handle */, AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
102 ASSERT_TRUE(result2.callSuccessful);
103 auto result2_time = getTime();
104 EXPECT_EQ(ErrorCode::OK, result2.error);
105 EXPECT_EQ(2U, result2.token.challenge);
106 EXPECT_EQ(SecLevel(), result2.token.securityLevel);
107 EXPECT_EQ(0U, result2.token.parametersVerified.size())
108 << "We didn't supply any parameters to verify";
109
110 auto host_time_delta = result2_time - result1_time;
111
112 EXPECT_GE(host_time_delta, time_to_sleep)
113 << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
114 EXPECT_LE(host_time_delta, time_to_sleep + 100)
115 << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
116 << " ms? That's awful!";
117
118 auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
119
120 // If not too much else is going on on the system, the time delta should be quite close. Allow
121 // 20 ms of slop just to avoid test flakiness.
122 //
123 // TODO(swillden): see if we can output values so they can be gathered across many runs and
124 // report if times aren't nearly always <1ms apart.
125 EXPECT_LE(host_time_delta, km_time_delta + 20);
126 EXPECT_LE(km_time_delta, host_time_delta + 20);
127 ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
128 ASSERT_NE(0,
129 memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
130 }
131
132 /*
133 * Test that the mac changes when the time stamp changes. This is does not guarantee that the time
134 * stamp is included in the mac but on failure we know that it is not. Other than in the test
135 * case above we call verifyAuthorization with the exact same set of parameters.
136 */
TEST_P(VerificationTokenTest,MacChangesOnChangingTimestamp)137 TEST_P(VerificationTokenTest, MacChangesOnChangingTimestamp) {
138 auto result1 =
139 verifyAuthorization(0 /* operation handle */,
140 AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
141 ASSERT_TRUE(result1.callSuccessful);
142 auto result1_time = getTime();
143
144 if (SecLevel() == SecurityLevel::STRONGBOX) {
145 // StrongBox should not implement verifyAuthorization.
146 EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
147 return;
148 }
149
150 EXPECT_EQ(ErrorCode::OK, result1.error);
151 EXPECT_EQ(0U, result1.token.challenge);
152 EXPECT_EQ(SecLevel(), result1.token.securityLevel);
153 EXPECT_EQ(0U, result1.token.parametersVerified.size())
154 << "We didn't supply any parameters to verify";
155 EXPECT_GT(result1.token.timestamp, 0U);
156
157 constexpr uint32_t time_to_sleep = 200;
158 sleep_ms(time_to_sleep);
159
160 auto result2 =
161 verifyAuthorization(0 /* operation handle */,
162 AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
163 ASSERT_TRUE(result2.callSuccessful);
164 auto result2_time = getTime();
165 EXPECT_EQ(ErrorCode::OK, result2.error);
166 EXPECT_EQ(0U, result2.token.challenge);
167 EXPECT_EQ(SecLevel(), result2.token.securityLevel);
168 EXPECT_EQ(0U, result2.token.parametersVerified.size())
169 << "We didn't supply any parameters to verify";
170
171 auto host_time_delta = result2_time - result1_time;
172
173 EXPECT_GE(host_time_delta, time_to_sleep)
174 << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
175 EXPECT_LE(host_time_delta, time_to_sleep + 100)
176 << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
177 << " ms? That's awful!";
178
179 auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
180
181 EXPECT_LE(host_time_delta, km_time_delta + 20);
182 EXPECT_LE(km_time_delta, host_time_delta + 20);
183 ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
184 ASSERT_NE(0,
185 memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
186 }
187
188 INSTANTIATE_KEYMASTER_HIDL_TEST(VerificationTokenTest);
189
190 } // namespace test
191 } // namespace V4_0
192 } // namespace keymaster
193 } // namespace hardware
194 } // namespace android
195