Respect limited requirements for Strongbox KM implementations

With this patch the KM VTS test apply the restricted requirements on
supported key sizes, EC curves, and Digests to Strongbox keymaster
implementations.

Also amend tests to use Update().

Test: Yes it is
Bug: 74519020
Change-Id: Ibec9c3398671f81dbc0ecf78e554726276160579
This commit is contained in:
nagendra modadugu 2018-06-05 11:05:19 -07:00 committed by Janis Danisevskis
parent 79db3ec849
commit 3a7e2cade3
3 changed files with 203 additions and 44 deletions

View file

@ -16,6 +16,9 @@
#include "KeymasterHidlTest.h"
#include <vector>
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <keymasterV4_0/key_param_output.h>
@ -383,12 +386,18 @@ string KeymasterHidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose ope
AuthorizationSet begin_out_params;
EXPECT_EQ(ErrorCode::OK, Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
string output;
size_t consumed = 0;
AuthorizationSet update_params;
AuthorizationSet update_out_params;
EXPECT_EQ(ErrorCode::OK,
Update(op_handle_, update_params, message, &update_out_params, &output, &consumed));
string unused;
AuthorizationSet finish_params;
AuthorizationSet finish_out_params;
string output;
EXPECT_EQ(ErrorCode::OK,
Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message.substr(consumed), unused,
&finish_out_params, &output));
op_handle_ = kOpHandleSentinel;
out_params->push_back(begin_out_params);
@ -480,12 +489,20 @@ void KeymasterHidlTest::VerifyMessage(const HidlBuf& key_blob, const string& mes
ASSERT_EQ(ErrorCode::OK,
Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
string output;
AuthorizationSet update_params;
AuthorizationSet update_out_params;
size_t consumed;
ASSERT_EQ(ErrorCode::OK,
Update(op_handle_, update_params, message, &update_out_params, &output, &consumed));
EXPECT_TRUE(output.empty());
EXPECT_GT(consumed, 0U);
string unused;
AuthorizationSet finish_params;
AuthorizationSet finish_out_params;
string output;
EXPECT_EQ(ErrorCode::OK,
Finish(op_handle_, finish_params, message, signature, &finish_out_params, &output));
EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message.substr(consumed), signature,
&finish_out_params, &output));
op_handle_ = kOpHandleSentinel;
EXPECT_TRUE(output.empty());
}
@ -585,6 +602,112 @@ std::pair<ErrorCode, HidlBuf> KeymasterHidlTest::UpgradeKey(const HidlBuf& key_b
});
return retval;
}
std::vector<uint32_t> KeymasterHidlTest::ValidKeySizes(Algorithm algorithm) {
switch (algorithm) {
case Algorithm::RSA:
switch (SecLevel()) {
case SecurityLevel::TRUSTED_ENVIRONMENT:
return {2048, 3072, 4096};
case SecurityLevel::STRONGBOX:
return {2048};
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
break;
}
break;
case Algorithm::EC:
switch (SecLevel()) {
case SecurityLevel::TRUSTED_ENVIRONMENT:
return {224, 256, 384, 521};
case SecurityLevel::STRONGBOX:
return {256};
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
break;
}
break;
case Algorithm::AES:
return {128, 256};
case Algorithm::TRIPLE_DES:
return {168};
case Algorithm::HMAC: {
std::vector<uint32_t> retval((512 - 64) / 8 + 1);
uint32_t size = 64 - 8;
std::generate(retval.begin(), retval.end(), [&]() { return (size += 8); });
return retval;
}
default:
CHECK(false) << "Invalid Algorithm: " << algorithm;
return {};
}
CHECK(false) << "Should be impossible to get here";
return {};
}
std::vector<uint32_t> KeymasterHidlTest::InvalidKeySizes(Algorithm algorithm) {
if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
CHECK(SecLevel() == SecurityLevel::STRONGBOX);
switch (algorithm) {
case Algorithm::RSA:
return {3072, 4096};
case Algorithm::EC:
return {224, 384, 521};
default:
return {};
}
}
std::vector<EcCurve> KeymasterHidlTest::ValidCurves() {
if (securityLevel_ == SecurityLevel::STRONGBOX) {
return {EcCurve::P_256};
} else {
return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
}
}
std::vector<EcCurve> KeymasterHidlTest::InvalidCurves() {
if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
CHECK(SecLevel() == SecurityLevel::STRONGBOX);
return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
}
std::initializer_list<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
std::vector<Digest> result;
switch (SecLevel()) {
case SecurityLevel::TRUSTED_ENVIRONMENT:
if (withNone) {
if (withMD5)
return {Digest::NONE, Digest::MD5, Digest::SHA1,
Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
Digest::SHA_2_512};
else
return {Digest::NONE, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
} else {
if (withMD5)
return {Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
else
return {Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
Digest::SHA_2_512};
}
break;
case SecurityLevel::STRONGBOX:
if (withNone)
return {Digest::NONE, Digest::SHA_2_256};
else
return {Digest::SHA_2_256};
break;
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
break;
}
CHECK(false) << "Should be impossible to get here";
return {};
}
std::vector<Digest> KeymasterHidlTest::InvalidDigests() {
return {};
}
} // namespace test
} // namespace V4_0

View file

@ -208,6 +208,15 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
static SecurityLevel SecLevel() { return securityLevel_; }
std::vector<uint32_t> ValidKeySizes(Algorithm algorithm);
std::vector<uint32_t> InvalidKeySizes(Algorithm algorithm);
std::vector<EcCurve> ValidCurves();
std::vector<EcCurve> InvalidCurves();
std::initializer_list<Digest> ValidDigests(bool withNone, bool withMD5);
std::vector<Digest> InvalidDigests();
HidlBuf key_blob_;
KeyCharacteristics key_characteristics_;
OperationHandle op_handle_ = kOpHandleSentinel;

View file

@ -376,7 +376,7 @@ class NewKeyGenerationTest : public KeymasterHidlTest {
* correct characteristics.
*/
TEST_F(NewKeyGenerationTest, Rsa) {
for (uint32_t key_size : {1024, 2048, 3072, 4096}) {
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@ -405,6 +405,23 @@ TEST_F(NewKeyGenerationTest, Rsa) {
}
}
/*
* NewKeyGenerationTest.NoInvalidRsaSizes
*
* Verifies that keymaster cannot generate any RSA key sizes that are designated as invalid.
*/
TEST_F(NewKeyGenerationTest, NoInvalidRsaSizes) {
for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(key_size, 3)
.Digest(Digest::NONE)
.Padding(PaddingMode::NONE),
&key_blob, &key_characteristics));
}
}
/*
* NewKeyGenerationTest.RsaNoDefaultSize
*
@ -425,7 +442,7 @@ TEST_F(NewKeyGenerationTest, RsaNoDefaultSize) {
* correct characteristics.
*/
TEST_F(NewKeyGenerationTest, Ecdsa) {
for (uint32_t key_size : {224, 256, 384, 521}) {
for (auto key_size : ValidKeySizes(Algorithm::EC)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
ASSERT_EQ(
@ -467,10 +484,18 @@ TEST_F(NewKeyGenerationTest, EcdsaDefaultSize) {
/*
* NewKeyGenerationTest.EcdsaInvalidSize
*
* Verifies that failing to specify an invalid key size for EC key generation returns
* UNSUPPORTED_KEY_SIZE.
* Verifies that specifying an invalid key size for EC key generation returns UNSUPPORTED_KEY_SIZE.
*/
TEST_F(NewKeyGenerationTest, EcdsaInvalidSize) {
for (auto key_size : InvalidKeySizes(Algorithm::EC)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
ASSERT_EQ(
ErrorCode::UNSUPPORTED_KEY_SIZE,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
&key_blob, &key_characteristics));
}
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(Digest::NONE)));
}
@ -482,6 +507,8 @@ TEST_F(NewKeyGenerationTest, EcdsaInvalidSize) {
* INVALID_ARGUMENT.
*/
TEST_F(NewKeyGenerationTest, EcdsaMismatchKeySize) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::INVALID_ARGUMENT,
GenerateKey(AuthorizationSetBuilder()
.EcdsaSigningKey(224)
@ -495,7 +522,7 @@ TEST_F(NewKeyGenerationTest, EcdsaMismatchKeySize) {
* Verifies that keymaster supports all required EC key sizes.
*/
TEST_F(NewKeyGenerationTest, EcdsaAllValidSizes) {
size_t valid_sizes[] = {224, 256, 384, 521};
auto valid_sizes = ValidKeySizes(Algorithm::EC);
for (size_t size : valid_sizes) {
EXPECT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(size).Digest(Digest::NONE)))
@ -506,13 +533,12 @@ TEST_F(NewKeyGenerationTest, EcdsaAllValidSizes) {
}
/*
* NewKeyGenerationTest.EcdsaAllValidCurves
* NewKeyGenerationTest.EcdsaInvalidCurves
*
* Verifies that keymaster supports all required EC curves.
* Verifies that keymaster does not support any curve designated as unsupported.
*/
TEST_F(NewKeyGenerationTest, EcdsaAllValidCurves) {
V4_0::EcCurve curves[] = {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
for (V4_0::EcCurve curve : curves) {
for (auto curve : ValidCurves()) {
EXPECT_EQ(
ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(curve).Digest(Digest::SHA_2_512)))
@ -529,8 +555,7 @@ TEST_F(NewKeyGenerationTest, EcdsaAllValidCurves) {
* characteristics.
*/
TEST_F(NewKeyGenerationTest, Hmac) {
for (auto digest : {Digest::MD5, Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256,
Digest::SHA_2_384, Digest::SHA_2_512}) {
for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
constexpr size_t key_size = 128;
@ -631,6 +656,8 @@ TEST_F(NewKeyGenerationTest, HmacCheckMinMacLengths) {
* Verifies that keymaster rejects HMAC key generation with multiple specified digest algorithms.
*/
TEST_F(NewKeyGenerationTest, HmacMultipleDigests) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
@ -665,7 +692,7 @@ typedef KeymasterHidlTest SigningOperationsTest;
*/
TEST_F(SigningOperationsTest, RsaSuccess) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(1024, 65537)
.RsaSigningKey(2048, 65537)
.Digest(Digest::NONE)
.Padding(PaddingMode::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED)));
@ -681,7 +708,7 @@ TEST_F(SigningOperationsTest, RsaSuccess) {
*/
TEST_F(SigningOperationsTest, RsaPssSha256Success) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(1024, 65537)
.RsaSigningKey(2048, 65537)
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PSS)
.Authorization(TAG_NO_AUTH_REQUIRED)));
@ -699,7 +726,7 @@ TEST_F(SigningOperationsTest, RsaPssSha256Success) {
*/
TEST_F(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(1024, 65537)
.RsaSigningKey(2048, 65537)
.Digest(Digest::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED)
.Padding(PaddingMode::NONE)));
@ -994,11 +1021,8 @@ TEST_F(SigningOperationsTest, RsaSignTooLargeMessage) {
* Verifies that ECDSA operations succeed with all possible key sizes and hashes.
*/
TEST_F(SigningOperationsTest, EcdsaAllSizesAndHashes) {
for (auto key_size : {224, 256, 384, 521}) {
for (auto digest : {
Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
Digest::SHA_2_512,
}) {
for (auto key_size : ValidKeySizes(Algorithm::EC)) {
for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
ErrorCode error = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(key_size)
@ -1021,7 +1045,7 @@ TEST_F(SigningOperationsTest, EcdsaAllSizesAndHashes) {
* Verifies that ECDSA operations succeed with all possible curves.
*/
TEST_F(SigningOperationsTest, EcdsaAllCurves) {
for (auto curve : {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521}) {
for (auto curve : ValidCurves()) {
ErrorCode error = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(curve)
@ -1076,8 +1100,7 @@ TEST_F(SigningOperationsTest, AesEcbSign) {
* Verifies that HMAC works with all digests.
*/
TEST_F(SigningOperationsTest, HmacAllDigests) {
for (auto digest : {Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
Digest::SHA_2_512}) {
for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.HmacKey(128)
@ -1308,15 +1331,15 @@ TEST_F(VerificationOperationsTest, RsaSuccess) {
* Verifies RSA signature/verification for all padding modes and digests.
*/
TEST_F(VerificationOperationsTest, RsaAllPaddingsAndDigests) {
ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
auto authorizations = AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaSigningKey(2048, 65537)
.Digest(Digest::NONE, Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512)
.Digest(ValidDigests(true /* withNone */, true /* withMD5 */))
.Padding(PaddingMode::NONE)
.Padding(PaddingMode::RSA_PSS)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
ASSERT_EQ(ErrorCode::OK, GenerateKey(authorizations));
string message(128, 'a');
string corrupt_message(message);
@ -1324,8 +1347,7 @@ TEST_F(VerificationOperationsTest, RsaAllPaddingsAndDigests) {
for (auto padding :
{PaddingMode::NONE, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN}) {
for (auto digest : {Digest::NONE, Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512}) {
for (auto digest : ValidDigests(true /* withNone */, true /* withMD5 */)) {
if (padding == PaddingMode::NONE && digest != Digest::NONE) {
// Digesting only makes sense with padding.
continue;
@ -1403,14 +1425,11 @@ TEST_F(VerificationOperationsTest, RsaAllPaddingsAndDigests) {
* Verifies ECDSA signature/verification for all digests and curves.
*/
TEST_F(VerificationOperationsTest, EcdsaAllDigestsAndCurves) {
auto digests = {
Digest::NONE, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512,
};
auto digests = ValidDigests(true /* withNone */, false /* withMD5 */);
string message = "1234567890";
string corrupt_message = "2234567890";
for (auto curve : {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521}) {
for (auto curve : ValidCurves()) {
ErrorCode error = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(curve)
@ -1722,6 +1741,7 @@ TEST_F(ImportKeyTest, EcdsaSuccess) {
* Verifies that importing and using an ECDSA P-521 key pair works correctly.
*/
TEST_F(ImportKeyTest, Ecdsa521Success) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(521)
@ -2054,8 +2074,7 @@ TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLarge) {
* Verifies that RSA-OAEP encryption operations work, with all digests.
*/
TEST_F(EncryptionOperationsTest, RsaOaepSuccess) {
auto digests = {Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
size_t key_size = 2048; // Need largish key for SHA-512 test.
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@ -2232,7 +2251,7 @@ TEST_F(EncryptionOperationsTest, RsaPkcs1TooLarge) {
TEST_F(EncryptionOperationsTest, EcdsaEncrypt) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(224)
.EcdsaSigningKey(256)
.Digest(Digest::NONE)));
auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params));
@ -2487,7 +2506,9 @@ TEST_F(EncryptionOperationsTest, AesIncremental) {
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:
@ -2803,6 +2824,8 @@ TEST_F(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
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);
@ -2814,7 +2837,7 @@ TEST_F(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
&plaintext, &input_consumed));
EXPECT_EQ(ciphertext.size(), input_consumed);
EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
EXPECT_EQ(message.length(), plaintext.length());
EXPECT_EQ(message, plaintext);
}
@ -3701,6 +3724,8 @@ typedef KeymasterHidlTest MaxOperationsTest;
* Verifies that the max uses per boot tag works correctly with AES keys.
*/
TEST_F(MaxOperationsTest, TestLimitAes) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.AesEncryptionKey(128)
@ -3726,6 +3751,8 @@ TEST_F(MaxOperationsTest, TestLimitAes) {
* Verifies that the max uses per boot tag works correctly with RSA keys.
*/
TEST_F(MaxOperationsTest, TestLimitRsa) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaSigningKey(1024, 65537)