Merge "Respect limited requirements for Strongbox KM implementations" into pi-dev

This commit is contained in:
TreeHugger Robot 2018-06-18 17:26:22 +00:00 committed by Android (Google) Code Review
commit 17be71d397
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)