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