From 33d75d090b63a14785f7c5474e24a0c7104afccf Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Thu, 9 May 2019 10:27:08 -0700 Subject: [PATCH] Verify mac change on time stamp change This test verifies that verification tokens with different time stamps do not have the same MAC. This may not guarantee that the MAC is computed correctly but it catches implementation that do not include the time stamp in the mac. It also checks that the MAC changes when both time stamp and challenge changes. Test: yes it is Bug: 131859731 Bug: 132288466 Bug: 132287277 Change-Id: I85aa1d873eff46df7a66fc69bd61a031e6e6fbe0 --- .../vts/functional/VerificationTokenTest.cpp | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp index 3876b16f3c..de2868334c 100644 --- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp +++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp @@ -124,6 +124,65 @@ TEST_F(VerificationTokenTest, TestCreation) { // report if times aren't nearly always <1ms apart. EXPECT_LE(host_time_delta, km_time_delta + 2); EXPECT_LE(km_time_delta, host_time_delta + 2); + ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size()); + ASSERT_NE(0, + memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size())); +} + +/* + * Test that the mac changes when the time stamp changes. This is does not guarantee that the time + * stamp is included in the mac but on failure we know that it is not. Other than in the test + * case above we call verifyAuthorization with the exact same set of parameters. + */ +TEST_F(VerificationTokenTest, MacChangesOnChangingTimestamp) { + auto result1 = + verifyAuthorization(0 /* operation handle */, + AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken()); + ASSERT_TRUE(result1.callSuccessful); + auto result1_time = getTime(); + + if (SecLevel() == SecurityLevel::STRONGBOX) { + // StrongBox should not implement verifyAuthorization. + EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error); + return; + } + + EXPECT_EQ(ErrorCode::OK, result1.error); + EXPECT_EQ(0U, result1.token.challenge); + EXPECT_EQ(SecLevel(), result1.token.securityLevel); + EXPECT_EQ(0U, result1.token.parametersVerified.size()) + << "We didn't supply any parameters to verify"; + EXPECT_GT(result1.token.timestamp, 0U); + + constexpr uint32_t time_to_sleep = 200; + sleep_ms(time_to_sleep); + + auto result2 = + verifyAuthorization(0 /* operation handle */, + AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken()); + ASSERT_TRUE(result2.callSuccessful); + auto result2_time = getTime(); + EXPECT_EQ(ErrorCode::OK, result2.error); + EXPECT_EQ(0U, result2.token.challenge); + EXPECT_EQ(SecLevel(), result2.token.securityLevel); + EXPECT_EQ(0U, result2.token.parametersVerified.size()) + << "We didn't supply any parameters to verify"; + + auto host_time_delta = result2_time - result1_time; + + EXPECT_GE(host_time_delta, time_to_sleep) + << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much"; + EXPECT_LE(host_time_delta, time_to_sleep + 20) + << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep) + << " ms? That's awful!"; + + auto km_time_delta = result2.token.timestamp - result1.token.timestamp; + + EXPECT_LE(host_time_delta, km_time_delta + 2); + EXPECT_LE(km_time_delta, host_time_delta + 2); + ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size()); + ASSERT_NE(0, + memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size())); } } // namespace test