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
19namespace android {
20namespace hardware {
21namespace keymaster {
22namespace V4_0 {
23namespace test {
24
25class VerificationTokenTest : public KeymasterHidlTest {
26   protected:
27    struct VerifyAuthorizationResult {
28        bool callSuccessful;
29        ErrorCode error;
30        VerificationToken token;
31    };
32
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
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
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 */
78TEST_F(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 + 10)
115        << "The verifyAuthorization call took more than 10 ms?  That's awful!";
116
117    auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
118
119    // If not too much else is going on on the system, the time delta should be quite close.  Allow
120    // 2 ms of slop just to avoid test flakiness.
121    //
122    // TODO(swillden): see if we can output values so they can be gathered across many runs and
123    // report if times aren't nearly always <1ms apart.
124    EXPECT_LE(host_time_delta, km_time_delta + 2);
125    EXPECT_LE(km_time_delta, host_time_delta + 2);
126}
127
128}  // namespace test
129}  // namespace V4_0
130}  // namespace keymaster
131}  // namespace hardware
132}  // namespace android
133