Merge "Split AESincremental VTS test into 4 Tests(For blockmodes-ECB,CBC,GCM,CTR)" am: 90019d46c2

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2007030

Change-Id: Ib7ed106fb09dcfa246bd0a31515fbbb358259de0
This commit is contained in:
Treehugger Robot 2022-03-04 18:07:02 +00:00 committed by Automerger Merge Worker
commit bfdd991c76
6 changed files with 224 additions and 172 deletions

View file

@ -443,6 +443,98 @@ string KeymasterHidlTest::MacMessage(const string& message, Digest digest, size_
AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
}
void KeymasterHidlTest::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
int message_size) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.AesEncryptionKey(128)
.BlockMode(block_mode)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
for (int increment = 1; increment <= message_size; ++increment) {
string message(message_size, 'a');
auto params = AuthorizationSetBuilder()
.BlockMode(block_mode)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
AuthorizationSet output_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
string ciphertext;
size_t input_consumed;
string to_send;
for (size_t i = 0; i < message.size(); i += increment) {
to_send.append(message.substr(i, increment));
EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
EXPECT_EQ(to_send.length(), input_consumed);
to_send = to_send.substr(input_consumed);
EXPECT_EQ(0U, to_send.length());
switch (block_mode) {
case BlockMode::ECB:
case BlockMode::CBC:
// Implementations must take as many blocks as possible, leaving less than
// a block.
EXPECT_LE(to_send.length(), 16U);
break;
case BlockMode::GCM:
case BlockMode::CTR:
// Implementations must always take all the data.
EXPECT_EQ(0U, to_send.length());
break;
}
}
EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
switch (block_mode) {
case BlockMode::GCM:
EXPECT_EQ(message.size() + 16, ciphertext.size());
break;
case BlockMode::CTR:
EXPECT_EQ(message.size(), ciphertext.size());
break;
case BlockMode::CBC:
case BlockMode::ECB:
EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
break;
}
auto iv = output_params.GetTagValue(TAG_NONCE);
switch (block_mode) {
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
params.push_back(TAG_NONCE, iv.value());
break;
case BlockMode::ECB:
EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
break;
}
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
<< "Decrypt begin() failed for block mode " << block_mode;
string plaintext;
for (size_t i = 0; i < ciphertext.size(); i += increment) {
to_send.append(ciphertext.substr(i, increment));
EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
to_send = to_send.substr(input_consumed);
}
ErrorCode error = Finish(to_send, &plaintext);
ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
<< " and increment " << increment;
if (error == ErrorCode::OK) {
ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
<< " and increment " << increment;
}
}
}
void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac) {
SCOPED_TRACE("CheckHmacTestVector");

View file

@ -166,6 +166,8 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
string MacMessage(const string& message, Digest digest, size_t mac_length);
void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
void CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac);

View file

@ -2932,105 +2932,39 @@ TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
}
/*
* EncryptionOperationsTest.AesIncremental
* EncryptionOperationsTest.AesEcbIncremental
*
* Verifies that AES works, all modes, when provided data in various size increments.
* Verifies that AES works for ECB block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesIncremental) {
auto block_modes = {
BlockMode::ECB, BlockMode::CBC, BlockMode::CTR, BlockMode::GCM,
};
TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
}
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.AesEncryptionKey(128)
.BlockMode(block_modes)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
/*
* EncryptionOperationsTest.AesCbcIncremental
*
* Verifies that AES works for CBC block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
}
for (int increment = 1; increment <= 240; ++increment) {
for (auto block_mode : block_modes) {
string message(240, 'a');
auto params = AuthorizationSetBuilder()
.BlockMode(block_mode)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
/*
* EncryptionOperationsTest.AesCtrIncremental
*
* Verifies that AES works for CTR block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
}
AuthorizationSet output_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
string ciphertext;
size_t input_consumed;
string to_send;
for (size_t i = 0; i < message.size(); i += increment) {
to_send.append(message.substr(i, increment));
EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
EXPECT_EQ(to_send.length(), input_consumed);
to_send = to_send.substr(input_consumed);
EXPECT_EQ(0U, to_send.length());
switch (block_mode) {
case BlockMode::ECB:
case BlockMode::CBC:
// Implementations must take as many blocks as possible, leaving less than
// a block.
EXPECT_LE(to_send.length(), 16U);
break;
case BlockMode::GCM:
case BlockMode::CTR:
// Implementations must always take all the data.
EXPECT_EQ(0U, to_send.length());
break;
}
}
EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
switch (block_mode) {
case BlockMode::GCM:
EXPECT_EQ(message.size() + 16, ciphertext.size());
break;
case BlockMode::CTR:
EXPECT_EQ(message.size(), ciphertext.size());
break;
case BlockMode::CBC:
case BlockMode::ECB:
EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
break;
}
auto iv = output_params.GetTagValue(TAG_NONCE);
switch (block_mode) {
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
params.push_back(TAG_NONCE, iv.value());
break;
case BlockMode::ECB:
EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
break;
}
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
<< "Decrypt begin() failed for block mode " << block_mode;
string plaintext;
for (size_t i = 0; i < ciphertext.size(); i += increment) {
to_send.append(ciphertext.substr(i, increment));
EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
to_send = to_send.substr(input_consumed);
}
ErrorCode error = Finish(to_send, &plaintext);
ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
<< " and increment " << increment;
if (error == ErrorCode::OK) {
ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
<< block_mode << " and increment " << increment;
}
}
}
/*
* EncryptionOperationsTest.AesGcmIncremental
*
* Verifies that AES works for GCM block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
}
struct AesCtrSp80038aTestVector {

View file

@ -665,6 +665,78 @@ string KeyMintAidlTestBase::MacMessage(const string& message, Digest digest, siz
AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
}
void KeyMintAidlTestBase::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
int message_size) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.AesEncryptionKey(128)
.BlockMode(block_mode)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
for (int increment = 1; increment <= message_size; ++increment) {
string message(message_size, 'a');
auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
if (block_mode == BlockMode::GCM) {
params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
}
AuthorizationSet output_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
string ciphertext;
string to_send;
for (size_t i = 0; i < message.size(); i += increment) {
EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
}
EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
<< "Error sending " << to_send << " with block mode " << block_mode;
switch (block_mode) {
case BlockMode::GCM:
EXPECT_EQ(message.size() + 16, ciphertext.size());
break;
case BlockMode::CTR:
EXPECT_EQ(message.size(), ciphertext.size());
break;
case BlockMode::CBC:
case BlockMode::ECB:
EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
break;
}
auto iv = output_params.GetTagValue(TAG_NONCE);
switch (block_mode) {
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
params.push_back(TAG_NONCE, iv->get());
break;
case BlockMode::ECB:
EXPECT_FALSE(iv) << "ECB mode should not generate IV";
break;
}
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
<< "Decrypt begin() failed for block mode " << block_mode;
string plaintext;
for (size_t i = 0; i < ciphertext.size(); i += increment) {
EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
}
ErrorCode error = Finish(to_send, &plaintext);
ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
<< " and increment " << increment;
if (error == ErrorCode::OK) {
ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
<< " and increment " << increment;
}
}
}
void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
Digest digest, const string& expected_mac) {
SCOPED_TRACE("CheckHmacTestVector");

View file

@ -169,6 +169,8 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
string MacMessage(const string& message, Digest digest, size_t mac_length);
void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
void CheckHmacTestVector(const string& key, const string& message, Digest digest,
const string& expected_mac);

View file

@ -5441,89 +5441,39 @@ TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
}
/*
* EncryptionOperationsTest.AesIncremental
* EncryptionOperationsTest.AesEcbIncremental
*
* Verifies that AES works, all modes, when provided data in various size increments.
* Verifies that AES works for ECB block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesIncremental) {
auto block_modes = {
BlockMode::ECB,
BlockMode::CBC,
BlockMode::CTR,
BlockMode::GCM,
};
TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
}
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.AesEncryptionKey(128)
.BlockMode(block_modes)
.Padding(PaddingMode::NONE)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
/*
* EncryptionOperationsTest.AesCbcIncremental
*
* Verifies that AES works for CBC block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
}
for (int increment = 1; increment <= 240; ++increment) {
for (auto block_mode : block_modes) {
string message(240, 'a');
auto params =
AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
if (block_mode == BlockMode::GCM) {
params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
}
/*
* EncryptionOperationsTest.AesCtrIncremental
*
* Verifies that AES works for CTR block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
}
AuthorizationSet output_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
string ciphertext;
string to_send;
for (size_t i = 0; i < message.size(); i += increment) {
EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
}
EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
<< "Error sending " << to_send << " with block mode " << block_mode;
switch (block_mode) {
case BlockMode::GCM:
EXPECT_EQ(message.size() + 16, ciphertext.size());
break;
case BlockMode::CTR:
EXPECT_EQ(message.size(), ciphertext.size());
break;
case BlockMode::CBC:
case BlockMode::ECB:
EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
break;
}
auto iv = output_params.GetTagValue(TAG_NONCE);
switch (block_mode) {
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
params.push_back(TAG_NONCE, iv->get());
break;
case BlockMode::ECB:
EXPECT_FALSE(iv) << "ECB mode should not generate IV";
break;
}
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
<< "Decrypt begin() failed for block mode " << block_mode;
string plaintext;
for (size_t i = 0; i < ciphertext.size(); i += increment) {
EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
}
ErrorCode error = Finish(to_send, &plaintext);
ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
<< " and increment " << increment;
if (error == ErrorCode::OK) {
ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
<< block_mode << " and increment " << increment;
}
}
}
/*
* EncryptionOperationsTest.AesGcmIncremental
*
* Verifies that AES works for GCM block mode, when provided data in various size increments.
*/
TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
}
struct AesCtrSp80038aTestVector {