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:
commit
bfdd991c76
6 changed files with 224 additions and 172 deletions
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue