Home | History | Annotate | Download | only in functional
      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 
     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  */
     78 TEST_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 + 20)
    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     // 2 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 + 2);
    126     EXPECT_LE(km_time_delta, host_time_delta + 2);
    127 }
    128 
    129 }  // namespace test
    130 }  // namespace V4_0
    131 }  // namespace keymaster
    132 }  // namespace hardware
    133 }  // namespace android
    134