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, &timespec));
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