1 /*
2 * Copyright (C) 2020 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 #define LOG_TAG "secureclock_test"
17 #include <android-base/logging.h>
18
19 #include <aidl/Gtest.h>
20 #include <aidl/Vintf.h>
21 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
22 #include <aidl/android/hardware/security/secureclock/ISecureClock.h>
23 #include <android/binder_manager.h>
24 #include <binder/ProcessState.h>
25 #include <gtest/gtest.h>
26 #include <vector>
27
28 namespace aidl::android::hardware::security::secureclock::test {
29 using Status = ::ndk::ScopedAStatus;
30 using ::aidl::android::hardware::security::keymint::ErrorCode;
31 using ::std::shared_ptr;
32 using ::std::string;
33 using ::std::vector;
34
35 class SecureClockAidlTest : public ::testing::TestWithParam<string> {
36 public:
37 struct TimestampTokenResult {
38 ErrorCode error;
39 TimeStampToken token;
40 };
41
getTimestampToken(int64_t in_challenge)42 TimestampTokenResult getTimestampToken(int64_t in_challenge) {
43 TimestampTokenResult result;
44 result.error =
45 GetReturnErrorCode(secureClock_->generateTimeStamp(in_challenge, &result.token));
46 return result;
47 }
48
getTime()49 uint64_t getTime() {
50 struct timespec timespec;
51 EXPECT_EQ(0, clock_gettime(CLOCK_BOOTTIME, ×pec));
52 return timespec.tv_sec * 1000 + timespec.tv_nsec / 1000000;
53 }
54
sleep_ms(uint32_t milliseconds)55 int sleep_ms(uint32_t milliseconds) {
56 struct timespec sleep_time = {static_cast<time_t>(milliseconds / 1000),
57 static_cast<long>(milliseconds % 1000) * 1000000};
58 while (sleep_time.tv_sec || sleep_time.tv_nsec) {
59 if (nanosleep(&sleep_time /* to wait */,
60 &sleep_time /* remaining (on interrruption) */) == 0) {
61 sleep_time = {};
62 } else {
63 if (errno != EINTR) return errno;
64 }
65 }
66 return 0;
67 }
68
GetReturnErrorCode(const Status & result)69 ErrorCode GetReturnErrorCode(const Status& result) {
70 if (result.isOk()) return ErrorCode::OK;
71
72 if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
73 return static_cast<ErrorCode>(result.getServiceSpecificError());
74 }
75
76 return ErrorCode::UNKNOWN_ERROR;
77 }
78
InitializeSecureClock(std::shared_ptr<ISecureClock> secureClock)79 void InitializeSecureClock(std::shared_ptr<ISecureClock> secureClock) {
80 ASSERT_NE(secureClock, nullptr);
81 secureClock_ = secureClock;
82 }
83
secureClock()84 ISecureClock& secureClock() { return *secureClock_; }
85
build_params()86 static vector<string> build_params() {
87 auto params = ::android::getAidlHalInstanceNames(ISecureClock::descriptor);
88 return params;
89 }
90
SetUp()91 void SetUp() override {
92 if (AServiceManager_isDeclared(GetParam().c_str())) {
93 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
94 InitializeSecureClock(ISecureClock::fromBinder(binder));
95 } else {
96 InitializeSecureClock(nullptr);
97 }
98 }
99
TearDown()100 void TearDown() override {}
101
102 private:
103 std::shared_ptr<ISecureClock> secureClock_;
104 };
105
106 /*
107 * The precise capabilities required to generate TimeStampToken will vary depending on the specific
108 * vendor implementations. The only thing we really can test is that tokens can be created by
109 * secureclock services, and that the timestamps increase as expected.
110 */
TEST_P(SecureClockAidlTest,TestCreation)111 TEST_P(SecureClockAidlTest, TestCreation) {
112 auto result1 = getTimestampToken(1 /* challenge */);
113 auto result1_time = getTime();
114 EXPECT_EQ(ErrorCode::OK, result1.error);
115 EXPECT_EQ(1U, result1.token.challenge);
116 EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
117 EXPECT_EQ(32U, result1.token.mac.size());
118
119 unsigned long time_to_sleep = 200;
120 sleep_ms(time_to_sleep);
121
122 auto result2 = getTimestampToken(2 /* challenge */);
123 auto result2_time = getTime();
124 EXPECT_EQ(ErrorCode::OK, result2.error);
125 EXPECT_EQ(2U, result2.token.challenge);
126 EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
127 EXPECT_EQ(32U, result2.token.mac.size());
128
129 auto host_time_delta = result2_time - result1_time;
130
131 EXPECT_GE(host_time_delta, time_to_sleep)
132 << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
133 EXPECT_LE(host_time_delta, time_to_sleep + 100)
134 << "The getTimestampToken call took " << (host_time_delta - time_to_sleep)
135 << " ms? That's awful!";
136 EXPECT_GE(result2.token.timestamp.milliSeconds, result1.token.timestamp.milliSeconds);
137 unsigned long km_time_delta =
138 result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
139 // 20 ms of slop just to avoid test flakiness.
140 EXPECT_LE(host_time_delta, km_time_delta + 20);
141 EXPECT_LE(km_time_delta, host_time_delta + 20);
142 ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
143 ASSERT_NE(0,
144 memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
145 }
146
147 /*
148 * Test that the mac changes when the time stamp changes. This is does not guarantee that the time
149 * stamp is included in the mac but on failure we know that it is not. Other than in the test
150 * case above we call getTimestampToken with the exact same set of parameters.
151 */
TEST_P(SecureClockAidlTest,MacChangesOnChangingTimestamp)152 TEST_P(SecureClockAidlTest, MacChangesOnChangingTimestamp) {
153 auto result1 = getTimestampToken(0 /* challenge */);
154 auto result1_time = getTime();
155 EXPECT_EQ(ErrorCode::OK, result1.error);
156 EXPECT_EQ(0U, result1.token.challenge);
157 EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
158 EXPECT_EQ(32U, result1.token.mac.size());
159
160 unsigned long time_to_sleep = 200;
161 sleep_ms(time_to_sleep);
162
163 auto result2 = getTimestampToken(1 /* challenge */);
164 auto result2_time = getTime();
165 EXPECT_EQ(ErrorCode::OK, result2.error);
166 EXPECT_EQ(1U, result2.token.challenge);
167 EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
168 EXPECT_EQ(32U, result2.token.mac.size());
169
170 auto host_time_delta = result2_time - result1_time;
171
172 EXPECT_GE(host_time_delta, time_to_sleep)
173 << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
174 EXPECT_LE(host_time_delta, time_to_sleep + 100)
175 << "The getTimestampToken call took " << (host_time_delta - time_to_sleep)
176 << " ms? That's awful!";
177
178 EXPECT_GE(result2.token.timestamp.milliSeconds, result1.token.timestamp.milliSeconds);
179 unsigned long km_time_delta =
180 result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
181
182 EXPECT_LE(host_time_delta, km_time_delta + 20);
183 EXPECT_LE(km_time_delta, host_time_delta + 20);
184 ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
185 ASSERT_NE(0,
186 memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
187 }
188
189 INSTANTIATE_TEST_SUITE_P(PerInstance, SecureClockAidlTest,
190 testing::ValuesIn(SecureClockAidlTest::build_params()),
191 ::android::PrintInstanceNameToString);
192 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureClockAidlTest);
193
194 } // namespace aidl::android::hardware::security::secureclock::test
195
main(int argc,char ** argv)196 int main(int argc, char** argv) {
197 ::testing::InitGoogleTest(&argc, argv);
198 return RUN_ALL_TESTS();
199 }
200