From 8ddc1c700d63d03336d168703664ecf28ce12c15 Mon Sep 17 00:00:00 2001 From: Rob Barnes Date: Fri, 13 Sep 2019 18:00:44 -0600 Subject: Add Keymaster VTS tests for some AES cases: 1. AES operation attempted with unauthorized purpose. 2. AES-GCM encryption performed with different nonces, should generate different ciphertexts. 3. AES-GCM encryption decryption round trip with delays between begin and update and finish. Bug: 133258003 Test: VtsHalKeymasterV4_0TargetTest Change-Id: Ia8b4b4b317ecff51b18e64dfa3b84bf77475812d --- keymaster/4.0/vts/functional/KeymasterHidlTest.cpp | 14 +++ keymaster/4.0/vts/functional/KeymasterHidlTest.h | 2 + .../4.0/vts/functional/keymaster_hidl_hal_test.cpp | 120 +++++++++++++++++++++ 3 files changed, 136 insertions(+) (limited to 'keymaster') diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp index 3af1df32d3..15d5fd8e69 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp @@ -611,6 +611,20 @@ string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_ return ciphertext; } +string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode, + PaddingMode padding, uint8_t mac_length_bits, + const HidlBuf& iv_in) { + SCOPED_TRACE("EncryptMessage"); + auto params = AuthorizationSetBuilder() + .BlockMode(block_mode) + .Padding(padding) + .Authorization(TAG_MAC_LENGTH, mac_length_bits) + .Authorization(TAG_NONCE, iv_in); + AuthorizationSet out_params; + string ciphertext = EncryptMessage(message, params, &out_params); + return ciphertext; +} + string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext, const AuthorizationSet& params) { SCOPED_TRACE("DecryptMessage"); diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h index 015fc43752..8fe223fcf0 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h @@ -201,6 +201,8 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { HidlBuf* iv_out); string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding, const HidlBuf& iv_in); + string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding, + uint8_t mac_length_bits, const HidlBuf& iv_in); string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext, const AuthorizationSet& params); diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 9e6cce7e97..dc1dfdcc7e 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -2705,6 +2705,40 @@ TEST_F(EncryptionOperationsTest, AesWrongMode) { AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE))); } +/* + * EncryptionOperationsTest.AesWrongPurpose + * + * Verifies that AES encryption fails in the correct way when an unauthorized purpose is specified. + */ +TEST_F(EncryptionOperationsTest, AesWrongPurpose) { + auto err = GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .AesKey(128) + .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT) + .Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Authorization(TAG_MIN_MAC_LENGTH, 128) + .Padding(PaddingMode::NONE)); + ASSERT_EQ(ErrorCode::OK, err) << "Got " << err; + + err = Begin(KeyPurpose::DECRYPT, + AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE)); + EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err; + + CheckedDeleteKey(); + + ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .AesKey(128) + .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT) + .Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Authorization(TAG_MIN_MAC_LENGTH, 128) + .Padding(PaddingMode::NONE))); + + err = Begin(KeyPurpose::ENCRYPT, + AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE)); + EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err; +} + /* * EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize * @@ -3224,6 +3258,92 @@ TEST_F(EncryptionOperationsTest, AesGcmRoundTripSuccess) { EXPECT_EQ(message, plaintext); } +/* + * EncryptionOperationsTest.AesGcmRoundTripWithDelaySuccess + * + * Verifies that AES GCM mode works, even when there's a long delay + * between operations. + */ +TEST_F(EncryptionOperationsTest, AesGcmRoundTripWithDelaySuccess) { + ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .AesEncryptionKey(128) + .Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Padding(PaddingMode::NONE) + .Authorization(TAG_MIN_MAC_LENGTH, 128))); + + string aad = "foobar"; + string message = "123456789012345678901234567890123456"; + + auto begin_params = AuthorizationSetBuilder() + .BlockMode(BlockMode::GCM) + .Padding(PaddingMode::NONE) + .Authorization(TAG_MAC_LENGTH, 128); + + auto update_params = + AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size()); + + // Encrypt + AuthorizationSet begin_out_params; + ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params)) + << "Begin encrypt"; + string ciphertext; + AuthorizationSet update_out_params; + sleep(5); + ASSERT_EQ(ErrorCode::OK, + Finish(op_handle_, update_params, message, "", &update_out_params, &ciphertext)); + + ASSERT_EQ(ciphertext.length(), message.length() + 16); + + // Grab nonce + begin_params.push_back(begin_out_params); + + // Decrypt. + ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt"; + string plaintext; + size_t input_consumed; + sleep(5); + ASSERT_EQ(ErrorCode::OK, Update(op_handle_, update_params, ciphertext, &update_out_params, + &plaintext, &input_consumed)); + EXPECT_EQ(ciphertext.size(), input_consumed); + sleep(5); + EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext)); + EXPECT_EQ(message.length(), plaintext.length()); + EXPECT_EQ(message, plaintext); +} + +/* + * EncryptionOperationsTest.AesGcmDifferentNonces + * + * Verifies that encrypting the same data with different nonces produces different outputs. + */ +TEST_F(EncryptionOperationsTest, AesGcmDifferentNonces) { + ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .AesEncryptionKey(128) + .Authorization(TAG_BLOCK_MODE, BlockMode::GCM) + .Padding(PaddingMode::NONE) + .Authorization(TAG_MIN_MAC_LENGTH, 128) + .Authorization(TAG_CALLER_NONCE))); + + string aad = "foobar"; + string message = "123456789012345678901234567890123456"; + string nonce1 = "000000000000"; + string nonce2 = "111111111111"; + string nonce3 = "222222222222"; + + string ciphertext1 = + EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce1)); + string ciphertext2 = + EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce2)); + string ciphertext3 = + EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce3)); + + ASSERT_NE(ciphertext1, ciphertext2); + ASSERT_NE(ciphertext1, ciphertext3); + ASSERT_NE(ciphertext2, ciphertext3); +} + /* * EncryptionOperationsTest.AesGcmTooShortTag * -- cgit v1.2.3