diff options
author | Orion Hodson <oth@google.com> | 2020-12-11 12:29:46 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-12-11 12:29:46 +0000 |
commit | 495ceb90fd2662ff1e060eb3ac8f33e3413c9507 (patch) | |
tree | 4f9e7667e236905c0d79bbdcba9ca5815fb6070a /security/keymint/aidl/vts/functional/KeyMintTest.cpp | |
parent | f3ff53da1a1213c378e4a7a0ec9f5b71da76b31a (diff) | |
parent | 1ffcdebadd7229af65c575dc1271084b17fe42d7 (diff) |
Merge "Revert "Move keymint to android.hardware.security.""
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintTest.cpp')
-rw-r--r-- | security/keymint/aidl/vts/functional/KeyMintTest.cpp | 4058 |
1 files changed, 0 insertions, 4058 deletions
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp deleted file mode 100644 index f9423a24a3..0000000000 --- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp +++ /dev/null @@ -1,4058 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "keymint_5_test" -#include <cutils/log.h> - -#include <signal.h> -#include <iostream> - -#include <openssl/evp.h> -#include <openssl/mem.h> -#include <openssl/x509.h> - -#include <cutils/properties.h> - -#include <android/hardware/security/keymint/KeyFormat.h> - -#include <keymint_support/attestation_record.h> -#include <keymint_support/key_param_output.h> -#include <keymint_support/openssl_utils.h> - -#include "KeyMintAidlTestBase.h" - -static bool arm_deleteAllKeys = false; -static bool dump_Attestations = false; - -using android::hardware::security::keymint::AuthorizationSet; -using android::hardware::security::keymint::KeyCharacteristics; -using android::hardware::security::keymint::KeyFormat; - -namespace android::hardware::security::keymint { - -bool operator==(const keymint::AuthorizationSet& a, const keymint::AuthorizationSet& b) { - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); -} - -} // namespace android::hardware::security::keymint - -namespace std { - -using namespace android::hardware::security::keymint; - -template <> -struct std::equal_to<KeyCharacteristics> { - bool operator()(const KeyCharacteristics& a, const KeyCharacteristics& b) const { - // This isn't very efficient. Oh, well. - AuthorizationSet a_sw(a.softwareEnforced); - AuthorizationSet b_sw(b.softwareEnforced); - AuthorizationSet a_tee(b.hardwareEnforced); - AuthorizationSet b_tee(b.hardwareEnforced); - - a_sw.Sort(); - b_sw.Sort(); - a_tee.Sort(); - b_tee.Sort(); - - return ((a_sw == b_sw) && (a_tee == b_tee)); - } -}; - -} // namespace std - -namespace android::hardware::security::keymint::test { - -namespace { - -template <TagType tag_type, Tag tag, typename ValueT> -bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) { - auto it = std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) { - return param.tag == tag && accessTagValue(ttag, param) == expected_value; - }); - return (it != set.end()); -} - -template <TagType tag_type, Tag tag> -bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag>) { - auto it = std::find_if(set.begin(), set.end(), - [&](const KeyParameter& param) { return param.tag == tag; }); - return (it != set.end()); -} - -constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9' - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -string hex2str(string a) { - string b; - size_t num = a.size() / 2; - b.resize(num); - for (size_t i = 0; i < num; i++) { - b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]); - } - return b; -} - -string rsa_key = - hex2str("30820275020100300d06092a864886f70d01010105000482025f3082025b" - "02010002818100c6095409047d8634812d5a218176e45c41d60a75b13901" - "f234226cffe776521c5a77b9e389417b71c0b6a44d13afe4e4a2805d46c9" - "da2935adb1ff0c1f24ea06e62b20d776430a4d435157233c6f916783c30e" - "310fcbd89b85c2d56771169785ac12bca244abda72bfb19fc44d27c81e1d" - "92de284f4061edfd99280745ea6d2502030100010281801be0f04d9cae37" - "18691f035338308e91564b55899ffb5084d2460e6630257e05b3ceab0297" - "2dfabcd6ce5f6ee2589eb67911ed0fac16e43a444b8c861e544a05933657" - "72f8baf6b22fc9e3c5f1024b063ac080a7b2234cf8aee8f6c47bbf4fd3ac" - "e7240290bef16c0b3f7f3cdd64ce3ab5912cf6e32f39ab188358afcccd80" - "81024100e4b49ef50f765d3b24dde01aceaaf130f2c76670a91a61ae08af" - "497b4a82be6dee8fcdd5e3f7ba1cfb1f0c926b88f88c92bfab137fba2285" - "227b83c342ff7c55024100ddabb5839c4c7f6bf3d4183231f005b31aa58a" - "ffdda5c79e4cce217f6bc930dbe563d480706c24e9ebfcab28a6cdefd324" - "b77e1bf7251b709092c24ff501fd91024023d4340eda3445d8cd26c14411" - "da6fdca63c1ccd4b80a98ad52b78cc8ad8beb2842c1d280405bc2f6c1bea" - "214a1d742ab996b35b63a82a5e470fa88dbf823cdd02401b7b57449ad30d" - "1518249a5f56bb98294d4b6ac12ffc86940497a5a5837a6cf946262b4945" - "26d328c11e1126380fde04c24f916dec250892db09a6d77cdba351024077" - "62cd8f4d050da56bd591adb515d24d7ccd32cca0d05f866d583514bd7324" - "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3" - "3492d6"); - -string ec_256_key = - hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30" - "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032" - "99986481f3a4d859a14403420004bf85d7720d07c25461683bc648b4778a" - "9a14dd8a024e3bdd8c7ddd9ab2b528bbc7aa1b51f14ebbbb0bd0ce21bcc4" - "1c6eb00083cf3376d11fd44949e0b2183bfe"); - -string ec_521_key = - hex2str("3081EE020100301006072A8648CE3D020106052B810400230481D63081D3" - "02010104420011458C586DB5DAA92AFAB03F4FE46AA9D9C3CE9A9B7A006A" - "8384BEC4C78E8E9D18D7D08B5BCFA0E53C75B064AD51C449BAE0258D54B9" - "4B1E885DED08ED4FB25CE9A1818903818600040149EC11C6DF0FA122C6A9" - "AFD9754A4FA9513A627CA329E349535A5629875A8ADFBE27DCB932C05198" - "6377108D054C28C6F39B6F2C9AF81802F9F326B842FF2E5F3C00AB7635CF" - "B36157FC0882D574A10D839C1A0C049DC5E0D775E2EE50671A208431BB45" - "E78E70BEFE930DB34818EE4D5C26259F5C6B8E28A652950F9F88D7B4B2C9" - "D9"); - -string ec_256_key_rfc5915 = - hex2str("308193020100301306072a8648ce3d020106082a8648ce3d030107047930" - "770201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3" - "8e8d21c9fa750c1da00a06082a8648ce3d030107a14403420004e2cc561e" - "e701da0ad0ef0d176bb0c919d42e79c393fdc1bd6c4010d85cf2cf8e68c9" - "05464666f98dad4f01573ba81078b3428570a439ba3229fbc026c550682f"); - -string ec_256_key_sec1 = - hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30" - "6b0201010420782370a8c8ce5537baadd04dcff079c8158cfa9c67b818b3" - "8e8d21c9fa750c1da14403420004e2cc561ee701da0ad0ef0d176bb0c919" - "d42e79c393fdc1bd6c4010d85cf2cf8e68c905464666f98dad4f01573ba8" - "1078b3428570a439ba3229fbc026c550682f"); - -struct RSA_Delete { - void operator()(RSA* p) { RSA_free(p); } -}; - -/* TODO(seleneh) add attestation verification codes like verify_chain() and - * attestation tests after we decided on the keymint 1 attestation changes. - */ - -std::string make_string(const uint8_t* data, size_t length) { - return std::string(reinterpret_cast<const char*>(data), length); -} - -template <size_t N> -std::string make_string(const uint8_t (&a)[N]) { - return make_string(a, N); -} - -class AidlBuf : public vector<uint8_t> { - typedef vector<uint8_t> super; - - public: - AidlBuf() {} - AidlBuf(const super& other) : super(other) {} - AidlBuf(super&& other) : super(std::move(other)) {} - explicit AidlBuf(const std::string& other) : AidlBuf() { *this = other; } - - AidlBuf& operator=(const super& other) { - super::operator=(other); - return *this; - } - - AidlBuf& operator=(super&& other) { - super::operator=(std::move(other)); - return *this; - } - - AidlBuf& operator=(const string& other) { - resize(other.size()); - for (size_t i = 0; i < other.size(); ++i) { - (*this)[i] = static_cast<uint8_t>(other[i]); - } - return *this; - } - - string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); } -}; - -} // namespace - -class NewKeyGenerationTest : public KeyMintAidlTestBase { - protected: - void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) { - // TODO(swillden): Distinguish which params should be in which auth list. - - AuthorizationSet auths(keyCharacteristics.hardwareEnforced); - auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced)); - - EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED)); - EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN)); - EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY)); - - // Verify that App ID, App data and ROT are NOT included. - EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST)); - EXPECT_FALSE(auths.Contains(TAG_APPLICATION_ID)); - EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA)); - - // Check that some unexpected tags/values are NOT present. - EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::ENCRYPT)); - EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT)); - EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U)); - - // Now check that unspecified, defaulted tags are correct. - EXPECT_TRUE(auths.Contains(TAG_CREATION_DATETIME)); - - EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version())) - << "OS version is " << os_version() << " key reported " - << auths.GetTagValue(TAG_OS_VERSION); - EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level())) - << "OS patch level is " << os_patch_level() << " key reported " - << auths.GetTagValue(TAG_OS_PATCHLEVEL); - } -}; - -/* - * NewKeyGenerationTest.Rsa - * - * Verifies that keymint can generate all required RSA key sizes, and that the resulting keys - * have correct characteristics. - */ -TEST_P(NewKeyGenerationTest, Rsa) { - for (auto key_size : ValidKeySizes(Algorithm::RSA)) { - vector<uint8_t> key_blob; - KeyCharacteristics key_characteristics; - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(key_size, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE), - &key_blob, &key_characteristics)); - - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - - AuthorizationSet crypto_params; - if (IsSecure()) { - crypto_params = key_characteristics.hardwareEnforced; - } else { - crypto_params = key_characteristics.softwareEnforced; - } - - EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA)); - EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) - << "Key size " << key_size << "missing"; - EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U)); - - CheckedDeleteKey(&key_blob); - } -} - -/* - * NewKeyGenerationTest.NoInvalidRsaSizes - * - * Verifies that keymint cannot generate any RSA key sizes that are designated as invalid. - */ -TEST_P(NewKeyGenerationTest, NoInvalidRsaSizes) { - for (auto key_size : InvalidKeySizes(Algorithm::RSA)) { - vector<uint8_t> key_blob; - KeyCharacteristics key_characteristics; - ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, - GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(key_size, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE), - &key_blob, &key_characteristics)); - } -} - -/* - * NewKeyGenerationTest.RsaNoDefaultSize - * - * Verifies that failing to specify a key size for RSA key generation returns - * UNSUPPORTED_KEY_SIZE. - */ -TEST_P(NewKeyGenerationTest, RsaNoDefaultSize) { - ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, - GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_ALGORITHM, Algorithm::RSA) - .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3U) - .SigningKey())); -} - -/* - * NewKeyGenerationTest.Ecdsa - * - * Verifies that keymint can generate all required EC key sizes, and that the resulting keys - * have correct characteristics. - */ -TEST_P(NewKeyGenerationTest, Ecdsa) { - for (auto key_size : ValidKeySizes(Algorithm::EC)) { - vector<uint8_t> key_blob; - KeyCharacteristics key_characteristics; - ASSERT_EQ(ErrorCode::OK, - GenerateKey( - AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE), - &key_blob, &key_characteristics)); - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - - AuthorizationSet crypto_params; - if (IsSecure()) { - crypto_params = key_characteristics.hardwareEnforced; - } else { - crypto_params = key_characteristics.softwareEnforced; - } - - EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC)); - EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) - << "Key size " << key_size << "missing"; - - CheckedDeleteKey(&key_blob); - } -} - -/* - * NewKeyGenerationTest.EcdsaDefaultSize - * - * Verifies that failing to specify a key size for EC key generation returns - * UNSUPPORTED_KEY_SIZE. - */ -TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) { - ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, - GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_ALGORITHM, Algorithm::EC) - .SigningKey() - .Digest(Digest::NONE))); -} - -/* - * NewKeyGenerationTest.EcdsaInvalidSize - * - * Verifies that specifying an invalid key size for EC key generation returns - * UNSUPPORTED_KEY_SIZE. - */ -TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) { - for (auto key_size : InvalidKeySizes(Algorithm::EC)) { - vector<uint8_t> 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))); -} - -/* - * NewKeyGenerationTest.EcdsaMismatchKeySize - * - * Verifies that specifying mismatched key size and curve for EC key generation returns - * INVALID_ARGUMENT. - */ -TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - - ASSERT_EQ(ErrorCode::INVALID_ARGUMENT, - GenerateKey(AuthorizationSetBuilder() - .EcdsaSigningKey(224) - .Authorization(TAG_EC_CURVE, EcCurve::P_256) - .Digest(Digest::NONE))); -} - -/* - * NewKeyGenerationTest.EcdsaAllValidSizes - * - * Verifies that keymint supports all required EC key sizes. - */ -TEST_P(NewKeyGenerationTest, EcdsaAllValidSizes) { - auto valid_sizes = ValidKeySizes(Algorithm::EC); - for (size_t size : valid_sizes) { - EXPECT_EQ(ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(size).Digest(Digest::NONE))) - << "Failed to generate size: " << size; - CheckedDeleteKey(); - } -} - -/* - * NewKeyGenerationTest.EcdsaInvalidCurves - * - * Verifies that keymint does not support any curve designated as unsupported. - */ -TEST_P(NewKeyGenerationTest, EcdsaAllValidCurves) { - Digest digest; - if (SecLevel() == SecurityLevel::STRONGBOX) { - digest = Digest::SHA_2_256; - } else { - digest = Digest::SHA_2_512; - } - for (auto curve : ValidCurves()) { - EXPECT_EQ(ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(curve).Digest(digest))) - << "Failed to generate key on curve: " << curve; - CheckedDeleteKey(); - } -} - -/* - * NewKeyGenerationTest.Hmac - * - * Verifies that keymint supports all required digests, and that the resulting keys have correct - * characteristics. - */ -TEST_P(NewKeyGenerationTest, Hmac) { - for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) { - vector<uint8_t> key_blob; - KeyCharacteristics key_characteristics; - constexpr size_t key_size = 128; - ASSERT_EQ(ErrorCode::OK, - GenerateKey( - AuthorizationSetBuilder().HmacKey(key_size).Digest(digest).Authorization( - TAG_MIN_MAC_LENGTH, 128), - &key_blob, &key_characteristics)); - - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - - AuthorizationSet hardwareEnforced = key_characteristics.hardwareEnforced; - AuthorizationSet softwareEnforced = key_characteristics.softwareEnforced; - if (IsSecure()) { - EXPECT_TRUE(hardwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC)); - EXPECT_TRUE(hardwareEnforced.Contains(TAG_KEY_SIZE, key_size)) - << "Key size " << key_size << "missing"; - } else { - EXPECT_TRUE(softwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC)); - EXPECT_TRUE(softwareEnforced.Contains(TAG_KEY_SIZE, key_size)) - << "Key size " << key_size << "missing"; - } - - CheckedDeleteKey(&key_blob); - } -} - -/* - * NewKeyGenerationTest.HmacCheckKeySizes - * - * Verifies that keymint supports all key sizes, and rejects all invalid key sizes. - */ -TEST_P(NewKeyGenerationTest, HmacCheckKeySizes) { - for (size_t key_size = 0; key_size <= 512; ++key_size) { - if (key_size < 64 || key_size % 8 != 0) { - // To keep this test from being very slow, we only test a random fraction of - // non-byte key sizes. We test only ~10% of such cases. Since there are 392 of - // them, we expect to run ~40 of them in each run. - if (key_size % 8 == 0 || random() % 10 == 0) { - EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, - GenerateKey(AuthorizationSetBuilder() - .HmacKey(key_size) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 256))) - << "HMAC key size " << key_size << " invalid"; - } - } else { - EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .HmacKey(key_size) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 256))) - << "Failed to generate HMAC key of size " << key_size; - CheckedDeleteKey(); - } - } -} - -/* - * NewKeyGenerationTest.HmacCheckMinMacLengths - * - * Verifies that keymint supports all required MAC lengths and rejects all invalid lengths. This - * test is probabilistic in order to keep the runtime down, but any failure prints out the - * specific MAC length that failed, so reproducing a failed run will be easy. - */ -TEST_P(NewKeyGenerationTest, HmacCheckMinMacLengths) { - for (size_t min_mac_length = 0; min_mac_length <= 256; ++min_mac_length) { - if (min_mac_length < 64 || min_mac_length % 8 != 0) { - // To keep this test from being very long, we only test a random fraction of - // non-byte lengths. We test only ~10% of such cases. Since there are 172 of them, - // we expect to run ~17 of them in each run. - if (min_mac_length % 8 == 0 || random() % 10 == 0) { - EXPECT_EQ(ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH, - GenerateKey(AuthorizationSetBuilder() - .HmacKey(128) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length))) - << "HMAC min mac length " << min_mac_length << " invalid."; - } - } else { - EXPECT_EQ(ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder() - .HmacKey(128) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length))) - << "Failed to generate HMAC key with min MAC length " << min_mac_length; - CheckedDeleteKey(); - } - } -} - -/* - * NewKeyGenerationTest.HmacMultipleDigests - * - * Verifies that keymint rejects HMAC key generation with multiple specified digest algorithms. - */ -TEST_P(NewKeyGenerationTest, HmacMultipleDigests) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - - ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST, - GenerateKey(AuthorizationSetBuilder() - .HmacKey(128) - .Digest(Digest::SHA1) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); -} - -/* - * NewKeyGenerationTest.HmacDigestNone - * - * Verifies that keymint rejects HMAC key generation with no digest or Digest::NONE - */ -TEST_P(NewKeyGenerationTest, HmacDigestNone) { - ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST, - GenerateKey(AuthorizationSetBuilder().HmacKey(128).Authorization(TAG_MIN_MAC_LENGTH, - 128))); - - ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST, - GenerateKey(AuthorizationSetBuilder() - .HmacKey(128) - .Digest(Digest::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(NewKeyGenerationTest); - -typedef KeyMintAidlTestBase SigningOperationsTest; - -/* - * SigningOperationsTest.RsaSuccess - * - * Verifies that raw RSA signature operations succeed. - */ -TEST_P(SigningOperationsTest, RsaSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED))); - string message = "12345678901234567890123456789012"; - string signature = SignMessage( - message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); -} - -/* - * SigningOperationsTest.RsaUseRequiresCorrectAppIdAppData - * - * Verifies that using an RSA key requires the correct app ID/data. - */ -TEST_P(SigningOperationsTest, RsaUseRequiresCorrectAppIdAppData) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_APPLICATION_ID, "clientid") - .Authorization(TAG_APPLICATION_DATA, "appdata"))); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_APPLICATION_ID, "clientid"))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_APPLICATION_DATA, "appdata"))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_APPLICATION_DATA, "appdata") - .Authorization(TAG_APPLICATION_ID, "clientid"))); - AbortIfNeeded(); -} - -/* - * SigningOperationsTest.RsaPssSha256Success - * - * Verifies that RSA-PSS signature operations succeed. - */ -TEST_P(SigningOperationsTest, RsaPssSha256Success) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_PSS) - .Authorization(TAG_NO_AUTH_REQUIRED))); - // Use large message, which won't work without digesting. - string message(1024, 'a'); - string signature = SignMessage( - message, - AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS)); -} - -/* - * SigningOperationsTest.RsaPaddingNoneDoesNotAllowOther - * - * Verifies that keymint rejects signature operations that specify a padding mode when the key - * supports only unpadded operations. - */ -TEST_P(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - string message = "12345678901234567890123456789012"; - string signature; - - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); -} - -/* - * SigningOperationsTest.NoUserConfirmation - * - * Verifies that keymint rejects signing operations for keys with - * TRUSTED_CONFIRMATION_REQUIRED and no valid confirmation token - * presented. - */ -TEST_P(SigningOperationsTest, NoUserConfirmation) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - ASSERT_EQ(ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(1024, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED))); - - const string message = "12345678901234567890123456789012"; - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); - string signature; - EXPECT_EQ(ErrorCode::NO_USER_CONFIRMATION, Finish(message, &signature)); -} - -/* - * SigningOperationsTest.RsaPkcs1Sha256Success - * - * Verifies that digested RSA-PKCS1 signature operations succeed. - */ -TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - string message(1024, 'a'); - string signature = SignMessage(message, AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)); -} - -/* - * SigningOperationsTest.RsaPkcs1NoDigestSuccess - * - * Verifies that undigested RSA-PKCS1 signature operations succeed. - */ -TEST_P(SigningOperationsTest, RsaPkcs1NoDigestSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - string message(53, 'a'); - string signature = SignMessage(message, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)); -} - -/* - * SigningOperationsTest.RsaPkcs1NoDigestTooLarge - * - * Verifies that undigested RSA-PKCS1 signature operations fail with the correct error code when - * given a too-long message. - */ -TEST_P(SigningOperationsTest, RsaPkcs1NoDigestTooLong) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - string message(257, 'a'); - - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - string signature; - EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &signature)); -} - -/* - * SigningOperationsTest.RsaPssSha512TooSmallKey - * - * Verifies that undigested RSA-PSS signature operations fail with the correct error code when - * used with a key that is too small for the message. - * - * A PSS-padded message is of length salt_size + digest_size + 16 (sizes in bits), and the - * keymint specification requires that salt_size == digest_size, so the message will be - * digest_size * 2 + - * 16. Such a message can only be signed by a given key if the key is at least that size. This - * test uses SHA512, which has a digest_size == 512, so the message size is 1040 bits, too large - * for a 1024-bit key. - */ -TEST_P(SigningOperationsTest, RsaPssSha512TooSmallKey) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(1024, 65537) - .Digest(Digest::SHA_2_512) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::RSA_PSS))); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_DIGEST, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::SHA_2_512) - .Padding(PaddingMode::RSA_PSS))); -} - -/* - * SigningOperationsTest.RsaNoPaddingTooLong - * - * Verifies that raw RSA signature operations fail with the correct error code when - * given a too-long message. - */ -TEST_P(SigningOperationsTest, RsaNoPaddingTooLong) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - // One byte too long - string message(2048 / 8 + 1, 'a'); - ASSERT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - string result; - ErrorCode finish_error_code = Finish(message, &result); - EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH || - finish_error_code == ErrorCode::INVALID_ARGUMENT); - - // Very large message that should exceed the transfer buffer size of any reasonable TEE. - message = string(128 * 1024, 'a'); - ASSERT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN))); - finish_error_code = Finish(message, &result); - EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH || - finish_error_code == ErrorCode::INVALID_ARGUMENT); -} - -/* - * SigningOperationsTest.RsaAbort - * - * Verifies that operations can be aborted correctly. Uses an RSA signing operation for the - * test, but the behavior should be algorithm and purpose-independent. - */ -TEST_P(SigningOperationsTest, RsaAbort) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - ASSERT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); - EXPECT_EQ(ErrorCode::OK, Abort()); - - // Another abort should fail - EXPECT_EQ(ErrorCode::INVALID_OPERATION_HANDLE, Abort()); - - // Set to sentinel, so TearDown() doesn't try to abort again. - op_.clear(); -} - -/* - * SigningOperationsTest.RsaUnsupportedPadding - * - * Verifies that RSA operations fail with the correct error (but key gen succeeds) when used - * with a padding mode inappropriate for RSA. - */ -TEST_P(SigningOperationsTest, RsaUnsupportedPadding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Digest(Digest::SHA_2_256 /* supported digest */) - .Padding(PaddingMode::PKCS7))); - ASSERT_EQ( - ErrorCode::UNSUPPORTED_PADDING_MODE, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::PKCS7))); -} - -/* - * SigningOperationsTest.RsaPssNoDigest - * - * Verifies that RSA PSS operations fail when no digest is used. PSS requires a digest. - */ -TEST_P(SigningOperationsTest, RsaNoDigest) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Digest(Digest::NONE) - .Padding(PaddingMode::RSA_PSS))); - ASSERT_EQ(ErrorCode::INCOMPATIBLE_DIGEST, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::RSA_PSS))); - - ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Padding(PaddingMode::RSA_PSS))); -} - -/* - * SigningOperationsTest.RsaPssNoDigest - * - * Verifies that RSA operations fail when no padding mode is specified. PaddingMode::NONE is - * supported in some cases (as validated in other tests), but a mode must be specified. - */ -TEST_P(SigningOperationsTest, RsaNoPadding) { - // Padding must be specified - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .RsaKey(2048, 65537) - .Authorization(TAG_NO_AUTH_REQUIRED) - .SigningKey() - .Digest(Digest::NONE))); - ASSERT_EQ(ErrorCode::UNSUPPORTED_PADDING_MODE, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE))); -} - -/* - * SigningOperationsTest.RsaShortMessage - * - * Verifies that raw RSA signatures succeed with a message shorter than the key size. - */ -TEST_P(SigningOperationsTest, RsaTooShortMessage) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE))); - - // Barely shorter - string message(2048 / 8 - 1, 'a'); - SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); - - // Much shorter - message = "a"; - SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); -} - -/* - * SigningOperationsTest.RsaSignWithEncryptionKey - * - * Verifies that RSA encryption keys cannot be used to sign. - */ -TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE))); - ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, - Begin(KeyPurpose::SIGN, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); -} - -/* - * SigningOperationsTest.RsaSignTooLargeMessage - * - * Verifies that attempting a raw signature of a message which is the same length as the key, - * but numerically larger than the public modulus, fails with the correct error. - */ -TEST_P(SigningOperationsTest, RsaSignTooLargeMessage) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE))); - - // Largest possible message will always be larger than the public modulus. - string message(2048 / 8, static_cast<char>(0xff)); - ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE))); - string signature; - ASSERT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &signature)); -} - -/* - * SigningOperationsTest.EcdsaAllSizesAndHashes - * - * Verifies that ECDSA operations succeed with all possible key sizes and hashes. - */ -TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) { - 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) - .Digest(digest)); - EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with size " << key_size - << " and digest " << digest; - if (error != ErrorCode::OK) continue; - - string message(1024, 'a'); - if (digest == Digest::NONE) message.resize(key_size / 8); - SignMessage(message, AuthorizationSetBuilder().Digest(digest)); - CheckedDeleteKey(); - } - } -} - -/* - * SigningOperationsTest.EcdsaAllCurves - * - * Verifies that ECDSA operations succeed with all possible curves. - */ -TEST_P(SigningOperationsTest, EcdsaAllCurves) { - for (auto curve : ValidCurves()) { - ErrorCode error = GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(curve) - .Digest(Digest::SHA_2_256)); - EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve; - if (error != ErrorCode::OK) continue; - - string message(1024, 'a'); - SignMessage(message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256)); - CheckedDeleteKey(); - } -} - -/* - * SigningOperationsTest.EcdsaNoDigestHugeData - * - * Verifies that ECDSA operations support very large messages, even without digesting. This - * should work because ECDSA actually only signs the leftmost L_n bits of the message, however - * large it may be. Not using digesting is a bad idea, but in some cases digesting is done by - * the framework. - */ -TEST_P(SigningOperationsTest, EcdsaNoDigestHugeData) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::NONE))); - string message(1 * 1024, 'a'); - SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE)); -} - -/* - * SigningOperationsTest.EcUseRequiresCorrectAppIdAppData - * - * Verifies that using an EC key requires the correct app ID/data. - */ -TEST_P(SigningOperationsTest, EcUseRequiresCorrectAppIdAppData) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::NONE) - .Authorization(TAG_APPLICATION_ID, "clientid") - .Authorization(TAG_APPLICATION_DATA, "appdata"))); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Authorization(TAG_APPLICATION_ID, "clientid"))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Authorization(TAG_APPLICATION_DATA, "appdata"))); - AbortIfNeeded(); - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::SIGN, AuthorizationSetBuilder() - .Digest(Digest::NONE) - .Authorization(TAG_APPLICATION_DATA, "appdata") - .Authorization(TAG_APPLICATION_ID, "clientid"))); - AbortIfNeeded(); -} - -/* - * SigningOperationsTest.AesEcbSign - * - * Verifies that attempts to use AES keys to sign fail in the correct way. - */ -TEST_P(SigningOperationsTest, AesEcbSign) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .SigningKey() - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB))); - - AuthorizationSet out_params; - EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, - Begin(KeyPurpose::SIGN, AuthorizationSet() /* in_params */, &out_params)); - EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, - Begin(KeyPurpose::VERIFY, AuthorizationSet() /* in_params */, &out_params)); -} - -/* - * SigningOperationsTest.HmacAllDigests - * - * Verifies that HMAC works with all digests. - */ -TEST_P(SigningOperationsTest, HmacAllDigests) { - for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .HmacKey(128) - .Digest(digest) - .Authorization(TAG_MIN_MAC_LENGTH, 160))) - << "Failed to create HMAC key with digest " << digest; - string message = "12345678901234567890123456789012"; - string signature = MacMessage(message, digest, 160); - EXPECT_EQ(160U / 8U, signature.size()) - << "Failed to sign with HMAC key with digest " << digest; - CheckedDeleteKey(); - } -} - -/* - * SigningOperationsTest.HmacSha256TooLargeMacLength - * - * Verifies that HMAC fails in the correct way when asked to generate a MAC larger than the - * digest size. - */ -TEST_P(SigningOperationsTest, HmacSha256TooLargeMacLength) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .HmacKey(128) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 256))); - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::UNSUPPORTED_MAC_LENGTH, Begin(KeyPurpose::SIGN, key_blob_, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MAC_LENGTH, 264), - &output_params)); -} - -/* - * SigningOperationsTest.HmacSha256TooSmallMacLength - * - * Verifies that HMAC fails in the correct way when asked to generate a MAC smaller than the - * specified minimum MAC length. - */ -TEST_P(SigningOperationsTest, HmacSha256TooSmallMacLength) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .HmacKey(128) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::SIGN, key_blob_, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MAC_LENGTH, 120), - &output_params)); -} - -/* - * SigningOperationsTest.HmacRfc4231TestCase3 - * - * Validates against the test vectors from RFC 4231 test case 3. - */ -TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) { - string key(20, 0xaa); - string message(50, 0xdd); - uint8_t sha_224_expected[] = { - 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, - 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea, - }; - uint8_t sha_256_expected[] = { - 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, - 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, - 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe, - }; - uint8_t sha_384_expected[] = { - 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, - 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, - 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d, - 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27, - }; - uint8_t sha_512_expected[] = { - 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, - 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, - 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, - 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37, - 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb, - }; - - CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected)); - if (SecLevel() != SecurityLevel::STRONGBOX) { - CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected)); - CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected)); - CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected)); - } -} - -/* - * SigningOperationsTest.HmacRfc4231TestCase5 - * - * Validates against the test vectors from RFC 4231 test case 5. - */ -TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) { - string key(20, 0x0c); - string message = "Test With Truncation"; - - uint8_t sha_224_expected[] = { - 0x0e, 0x2a, 0xea, 0x68, 0xa9, 0x0c, 0x8d, 0x37, - 0xc9, 0x88, 0xbc, 0xdb, 0x9f, 0xca, 0x6f, 0xa8, - }; - uint8_t sha_256_expected[] = { - 0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0, - 0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b, - }; - uint8_t sha_384_expected[] = { - 0x3a, 0xbf, 0x34, 0xc3, 0x50, 0x3b, 0x2a, 0x23, - 0xa4, 0x6e, 0xfc, 0x61, 0x9b, 0xae, 0xf8, 0x97, - }; - uint8_t sha_512_expected[] = { - 0x41, 0x5f, 0xad, 0x62, 0x71, 0x58, 0x0a, 0x53, - 0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6, - }; - - CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected)); - if (SecLevel() != SecurityLevel::STRONGBOX) { - CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected)); - CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected)); - CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected)); - } -} - -INSTANTIATE_KEYMINT_AIDL_TEST(SigningOperationsTest); - -typedef KeyMintAidlTestBase VerificationOperationsTest; - -/* - * VerificationOperationsTest.RsaSuccess - * - * Verifies that a simple RSA signature/verification sequence succeeds. - */ -TEST_P(VerificationOperationsTest, RsaSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE))); - string message = "12345678901234567890123456789012"; - string signature = SignMessage( - message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); - VerifyMessage(message, signature, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)); -} - -/* - * VerificationOperationsTest.RsaSuccess - * - * Verifies RSA signature/verification for all padding modes and digests. - */ -TEST_P(VerificationOperationsTest, RsaAllPaddingsAndDigests) { - auto authorizations = AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(ValidDigests(true /* withNone */, true /* withMD5 */)) - .Padding(PaddingMode::NONE) - .Padding(PaddingMode::RSA_PSS) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN); - - ASSERT_EQ(ErrorCode::OK, GenerateKey(authorizations)); - - string message(128, 'a'); - string corrupt_message(message); - ++corrupt_message[corrupt_message.size() / 2]; - - for (auto padding : - {PaddingMode::NONE, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN}) { - for (auto digest : ValidDigests(true /* withNone */, true /* withMD5 */)) { - if (padding == PaddingMode::NONE && digest != Digest::NONE) { - // Digesting only makes sense with padding. - continue; - } - - if (padding == PaddingMode::RSA_PSS && digest == Digest::NONE) { - // PSS requires digesting. - continue; - } - - string signature = - SignMessage(message, AuthorizationSetBuilder().Digest(digest).Padding(padding)); - VerifyMessage(message, signature, - AuthorizationSetBuilder().Digest(digest).Padding(padding)); - - /* TODO(seleneh) add exportkey tests back later when we have decided on - * the new api. - if (digest != Digest::NONE) { - // Verify with OpenSSL. - vector<uint8_t> pubkey; - ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey)); - - const uint8_t* p = pubkey.data(); - EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr, &p, pubkey.size())); - ASSERT_TRUE(pkey.get()); - - EVP_MD_CTX digest_ctx; - EVP_MD_CTX_init(&digest_ctx); - EVP_PKEY_CTX* pkey_ctx; - const EVP_MD* md = openssl_digest(digest); - ASSERT_NE(md, nullptr); - EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md, - nullptr, pkey.get())); - - switch (padding) { - case PaddingMode::RSA_PSS: - EXPECT_GT(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, - RSA_PKCS1_PSS_PADDING), 0); EXPECT_GT(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, - EVP_MD_size(md)), 0); break; case PaddingMode::RSA_PKCS1_1_5_SIGN: - // PKCS1 is the default; don't need to set anything. - break; - default: - FAIL(); - break; - } - - EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), - message.size())); EXPECT_EQ(1, EVP_DigestVerifyFinal(&digest_ctx, - reinterpret_cast<const - uint8_t*>(signature.data()), signature.size())); EVP_MD_CTX_cleanup(&digest_ctx); - } - */ - - // Corrupt signature shouldn't verify. - string corrupt_signature(signature); - ++corrupt_signature[corrupt_signature.size() / 2]; - - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::VERIFY, - AuthorizationSetBuilder().Digest(digest).Padding(padding))); - string result; - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result)); - - // Corrupt message shouldn't verify - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::VERIFY, - AuthorizationSetBuilder().Digest(digest).Padding(padding))); - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result)); - } - } -} - -/* - * VerificationOperationsTest.RsaSuccess - * - * Verifies ECDSA signature/verification for all digests and curves. - */ -TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndCurves) { - auto digests = ValidDigests(true /* withNone */, false /* withMD5 */); - - string message = "1234567890"; - string corrupt_message = "2234567890"; - for (auto curve : ValidCurves()) { - ErrorCode error = GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(curve) - .Digest(digests)); - EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate key for EC curve " << curve; - if (error != ErrorCode::OK) { - continue; - } - - for (auto digest : digests) { - string signature = SignMessage(message, AuthorizationSetBuilder().Digest(digest)); - VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(digest)); - - /* TODO(seleneh) add exportkey tests back later when we have decided on - * the new api. - - // Verify with OpenSSL - if (digest != Digest::NONE) { - vector<uint8_t> pubkey; - ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey)) - << curve << ' ' << digest; - - const uint8_t* p = pubkey.data(); - EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr, &p, pubkey.size())); - ASSERT_TRUE(pkey.get()); - - EVP_MD_CTX digest_ctx; - EVP_MD_CTX_init(&digest_ctx); - EVP_PKEY_CTX* pkey_ctx; - const EVP_MD* md = openssl_digest(digest); - - EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md, - nullptr, pkey.get())) - << curve << ' ' << digest; - - EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), - message.size())) - << curve << ' ' << digest; - - EXPECT_EQ(1, - EVP_DigestVerifyFinal(&digest_ctx, - reinterpret_cast<const - uint8_t*>(signature.data()), signature.size())) - << curve << ' ' << digest; - - EVP_MD_CTX_cleanup(&digest_ctx); - } - */ - // Corrupt signature shouldn't verify. - string corrupt_signature(signature); - ++corrupt_signature[corrupt_signature.size() / 2]; - - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest))) - << curve << ' ' << digest; - - string result; - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result)) - << curve << ' ' << digest; - - // Corrupt message shouldn't verify - EXPECT_EQ(ErrorCode::OK, - Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest))) - << curve << ' ' << digest; - - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result)) - << curve << ' ' << digest; - } - - auto rc = DeleteKey(); - ASSERT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED); - } -} - -/* - * VerificationOperationsTest.HmacSigningKeyCannotVerify - * - * Verifies HMAC signing and verification, but that a signing key cannot be used to verify. - */ -TEST_P(VerificationOperationsTest, HmacSigningKeyCannotVerify) { - string key_material = "HelloThisIsAKey"; - - vector<uint8_t> signing_key, verification_key; - KeyCharacteristics signing_key_chars, verification_key_chars; - EXPECT_EQ(ErrorCode::OK, - ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_ALGORITHM, Algorithm::HMAC) - .Authorization(TAG_PURPOSE, KeyPurpose::SIGN) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 160), - KeyFormat::RAW, key_material, &signing_key, &signing_key_chars)); - EXPECT_EQ(ErrorCode::OK, - ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_ALGORITHM, Algorithm::HMAC) - .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 160), - KeyFormat::RAW, key_material, &verification_key, &verification_key_chars)); - - string message = "This is a message."; - string signature = SignMessage( - signing_key, message, - AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 160)); - - // Signing key should not work. - AuthorizationSet out_params; - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, - Begin(KeyPurpose::VERIFY, signing_key, - AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &out_params)); - - // Verification key should work. - VerifyMessage(verification_key, message, signature, - AuthorizationSetBuilder().Digest(Digest::SHA_2_256)); - - CheckedDeleteKey(&signing_key); - CheckedDeleteKey(&verification_key); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest); - -typedef KeyMintAidlTestBase ExportKeyTest; - -/* - * ExportKeyTest.RsaUnsupportedKeyFormat - * - * Verifies that attempting to export RSA keys in PKCS#8 format fails with the correct error. - */ -// TODO(seleneh) add ExportKey to GenerateKey -// check result - -class ImportKeyTest : public KeyMintAidlTestBase { - public: - template <TagType tag_type, Tag tag, typename ValueT> - void CheckCryptoParam(TypedTag<tag_type, tag> ttag, ValueT expected) { - SCOPED_TRACE("CheckCryptoParam"); - if (IsSecure()) { - EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, ttag, expected)) - << "Tag " << tag << " with value " << expected << " not found"; - EXPECT_FALSE(contains(key_characteristics_.softwareEnforced, ttag)) - << "Tag " << tag << " found"; - } else { - EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, ttag, expected)) - << "Tag " << tag << " with value " << expected << " not found"; - EXPECT_FALSE(contains(key_characteristics_.hardwareEnforced, ttag)) - << "Tag " << tag << " found"; - } - } - - void CheckOrigin() { - SCOPED_TRACE("CheckOrigin"); - if (IsSecure()) { - EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, TAG_ORIGIN, - KeyOrigin::IMPORTED)); - } else { - EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, TAG_ORIGIN, - KeyOrigin::IMPORTED)); - } - } -}; - -/* - * ImportKeyTest.RsaSuccess - * - * Verifies that importing and using an RSA key pair works correctly. - */ -TEST_P(ImportKeyTest, RsaSuccess) { - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(1024, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_PSS), - KeyFormat::PKCS8, rsa_key)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA); - CheckCryptoParam(TAG_KEY_SIZE, 1024U); - CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_PSS); - CheckOrigin(); - - string message(1024 / 8, 'a'); - auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS); - string signature = SignMessage(message, params); - VerifyMessage(message, signature, params); -} - -/* - * ImportKeyTest.RsaKeySizeMismatch - * - * Verifies that importing an RSA key pair with a size that doesn't match the key fails in the - * correct way. - */ -TEST_P(ImportKeyTest, RsaKeySizeMismatch) { - ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH, - ImportKey(AuthorizationSetBuilder() - .RsaSigningKey(2048 /* Doesn't match key */, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE), - KeyFormat::PKCS8, rsa_key)); -} - -/* - * ImportKeyTest.RsaPublicExponentMismatch - * - * Verifies that importing an RSA key pair with a public exponent that doesn't match the key - * fails in the correct way. - */ -TEST_P(ImportKeyTest, RsaPublicExponentMismatch) { - ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH, - ImportKey(AuthorizationSetBuilder() - .RsaSigningKey(1024, 3 /* Doesn't match key */) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE), - KeyFormat::PKCS8, rsa_key)); -} - -/* - * ImportKeyTest.EcdsaSuccess - * - * Verifies that importing and using an ECDSA P-256 key pair works correctly. - */ -TEST_P(ImportKeyTest, EcdsaSuccess) { - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::SHA_2_256), - KeyFormat::PKCS8, ec_256_key)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); - CheckCryptoParam(TAG_KEY_SIZE, 256U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256); - - CheckOrigin(); - - string message(32, 'a'); - auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); - string signature = SignMessage(message, params); - VerifyMessage(message, signature, params); -} - -/* - * ImportKeyTest.EcdsaP256RFC5915Success - * - * Verifies that importing and using an ECDSA P-256 key pair encoded using RFC5915 works - * correctly. - */ -TEST_P(ImportKeyTest, EcdsaP256RFC5915Success) { - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::SHA_2_256), - KeyFormat::PKCS8, ec_256_key_rfc5915)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); - CheckCryptoParam(TAG_KEY_SIZE, 256U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256); - - CheckOrigin(); - - string message(32, 'a'); - auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); - string signature = SignMessage(message, params); - VerifyMessage(message, signature, params); -} - -/* - * ImportKeyTest.EcdsaP256SEC1Success - * - * Verifies that importing and using an ECDSA P-256 key pair encoded using SEC1 works correctly. - */ -TEST_P(ImportKeyTest, EcdsaP256SEC1Success) { - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::SHA_2_256), - KeyFormat::PKCS8, ec_256_key_sec1)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); - CheckCryptoParam(TAG_KEY_SIZE, 256U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256); - - CheckOrigin(); - - string message(32, 'a'); - auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); - string signature = SignMessage(message, params); - VerifyMessage(message, signature, params); -} - -/* - * ImportKeyTest.Ecdsa521Success - * - * Verifies that importing and using an ECDSA P-521 key pair works correctly. - */ -TEST_P(ImportKeyTest, Ecdsa521Success) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(521) - .Digest(Digest::SHA_2_256), - KeyFormat::PKCS8, ec_521_key)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC); - CheckCryptoParam(TAG_KEY_SIZE, 521U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_521); - CheckOrigin(); - - string message(32, 'a'); - auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256); - string signature = SignMessage(message, params); - VerifyMessage(message, signature, params); -} - -/* - * ImportKeyTest.EcdsaSizeMismatch - * - * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the - * correct way. - */ -TEST_P(ImportKeyTest, EcdsaSizeMismatch) { - ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH, - ImportKey(AuthorizationSetBuilder() - .EcdsaSigningKey(224 /* Doesn't match key */) - .Digest(Digest::NONE), - KeyFormat::PKCS8, ec_256_key)); -} - -/* - * ImportKeyTest.EcdsaCurveMismatch - * - * Verifies that importing an ECDSA key pair with a curve that doesn't match the key fails in - * the correct way. - */ -TEST_P(ImportKeyTest, EcdsaCurveMismatch) { - ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH, - ImportKey(AuthorizationSetBuilder() - .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */) - .Digest(Digest::NONE), - KeyFormat::PKCS8, ec_256_key)); -} - -/* - * ImportKeyTest.AesSuccess - * - * Verifies that importing and using an AES key works. - */ -TEST_P(ImportKeyTest, AesSuccess) { - string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(key.size() * 8) - .EcbMode() - .Padding(PaddingMode::PKCS7), - KeyFormat::RAW, key)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::AES); - CheckCryptoParam(TAG_KEY_SIZE, 128U); - CheckCryptoParam(TAG_PADDING, PaddingMode::PKCS7); - CheckCryptoParam(TAG_BLOCK_MODE, BlockMode::ECB); - CheckOrigin(); - - string message = "Hello World!"; - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - string ciphertext = EncryptMessage(message, params); - string plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); -} - -/* - * ImportKeyTest.AesSuccess - * - * Verifies that importing and using an HMAC key works. - */ -TEST_P(ImportKeyTest, HmacKeySuccess) { - string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .HmacKey(key.size() * 8) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, 256), - KeyFormat::RAW, key)); - - CheckCryptoParam(TAG_ALGORITHM, Algorithm::HMAC); - CheckCryptoParam(TAG_KEY_SIZE, 128U); - CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256); - CheckOrigin(); - - string message = "Hello World!"; - string signature = MacMessage(message, Digest::SHA_2_256, 256); - VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256)); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest); - -auto wrapped_key = hex2str( - "3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac8" - "4b59b30b455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e0" - "97474febc981195b1d13a69086c0863f66a7b7fdb48792227b1ac5e2489febdf087ab5486483033a6f001c" - "a5d1ec1e27f5c30f4cec2642074a39ae68aee552e196627a8e3d867e67a8c01b11e75f13cca0a97ab668b5" - "0cda07a8ecb7cd8e3dd7009c9636534f6f239cffe1fc8daa466f78b676c7119efb96bce4e69ca2a25d0b34" - "ed9c3ff999b801597d5220e307eaa5bee507fb94d1fa69f9e519b2de315bac92c36f2ea1fa1df4478c0dde" - "deae8c70e0233cd098040cd796b02c370f1fa4cc0124f1302e0201033029a1083106020100020101a20302" - "0120a30402020100a4053103020101a6053103020140bf83770205000420ccd540855f833a5e1480bfd2d3" - "6faf3aeee15df5beabe2691bc82dde2a7aa910041064c9f689c60ff6223ab6e6999e0eb6e5"); - -auto wrapped_key_masked = hex2str( - "3082017902010004820100aad93ed5924f283b4bb5526fbe7a1412f9d9749ec30db9062b29e574a8546f33" - "c88732452f5b8e6a391ee76c39ed1712c61d8df6213dec1cffbc17a8c6d04c7b30893d8daa9b2015213e21" - "946821553207f8f9931c4caba23ed3bee28b36947e47f10e0a5c3dc51c988a628daad3e5e1f4005e79c2d5" - "a96c284b4b8d7e4948f331e5b85dd5a236f85579f3ea1d1b848487470bdb0ab4f81a12bee42c99fe0df4be" - "e3759453e69ad1d68a809ce06b949f7694a990429b2fe81e066ff43e56a21602db70757922a4bcc23ab89f" - "1e35da77586775f423e519c2ea394caf48a28d0c8020f1dcf6b3a68ec246f615ae96dae9a079b1f6eb9590" - "33c1af5c125fd94168040c6d9721d08589581ab49204a3302e0201033029a1083106020100020101a20302" - "0120a30402020100a4053103020101a6053103020140bf83770205000420a61c6e247e25b3e6e69aa78eb0" - "3c2d4ac20d1f99a9a024a76f35c8e2cab9b68d04102560c70109ae67c030f00b98b512a670"); - -auto wrapping_key = hex2str( - "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d" - "8900ce56b0067f7d70e1fc653f3f34d194c1fed50018fb43db937b06e673a837313d56b1c725150a3fef86" - "acbddc41bb759c2854eae32d35841efb5c18d82bc90a1cb5c1d55adf245b02911f0b7cda88c421ff0ebafe" - "7c0d23be312d7bd5921ffaea1347c157406fef718f682643e4e5d33c6703d61c0cf7ac0bf4645c11f5c137" - "4c3886427411c449796792e0bef75dec858a2123c36753e02a95a96d7c454b504de385a642e0dfc3e60ac3" - "a7ee4991d0d48b0172a95f9536f02ba13cecccb92b727db5c27e5b2f5cec09600b286af5cf14c42024c61d" - "dfe71c2a8d7458f185234cb00e01d282f10f8fc6721d2aed3f4833cca2bd8fa62821dd5502030100010282" - "0100431447b6251908112b1ee76f99f3711a52b6630960046c2de70de188d833f8b8b91e4d785caeeeaf4f" - "0f74414e2cda40641f7fe24f14c67a88959bdb27766df9e710b630a03adc683b5d2c43080e52bee71e9eae" - "b6de297a5fea1072070d181c822bccff087d63c940ba8a45f670feb29fb4484d1c95e6d2579ba02aae0a00" - "900c3ebf490e3d2cd7ee8d0e20c536e4dc5a5097272888cddd7e91f228b1c4d7474c55b8fcd618c4a957bb" - "ddd5ad7407cc312d8d98a5caf7e08f4a0d6b45bb41c652659d5a5ba05b663737a8696281865ba20fbdd7f8" - "51e6c56e8cbe0ddbbf24dc03b2d2cb4c3d540fb0af52e034a2d06698b128e5f101e3b51a34f8d8b4f86181" - "02818100de392e18d682c829266cc3454e1d6166242f32d9a1d10577753e904ea7d08bff841be5bac82a16" - "4c5970007047b8c517db8f8f84e37bd5988561bdf503d4dc2bdb38f885434ae42c355f725c9a60f91f0788" - "e1f1a97223b524b5357fdf72e2f696bab7d78e32bf92ba8e1864eab1229e91346130748a6e3c124f9149d7" - "1c743502818100c95387c0f9d35f137b57d0d65c397c5e21cc251e47008ed62a542409c8b6b6ac7f8967b3" - "863ca645fcce49582a9aa17349db6c4a95affdae0dae612e1afac99ed39a2d934c880440aed8832f984316" - "3a47f27f392199dc1202f9a0f9bd08308007cb1e4e7f58309366a7de25f7c3c9b880677c068e1be936e812" - "88815252a8a102818057ff8ca1895080b2cae486ef0adfd791fb0235c0b8b36cd6c136e52e4085f4ea5a06" - "3212a4f105a3764743e53281988aba073f6e0027298e1c4378556e0efca0e14ece1af76ad0b030f27af6f0" - "ab35fb73a060d8b1a0e142fa2647e93b32e36d8282ae0a4de50ab7afe85500a16f43a64719d6e2b9439823" - "719cd08bcd03178102818100ba73b0bb28e3f81e9bd1c568713b101241acc607976c4ddccc90e65b6556ca" - "31516058f92b6e09f3b160ff0e374ec40d78ae4d4979fde6ac06a1a400c61dd31254186af30b22c10582a8" - "a43e34fe949c5f3b9755bae7baa7b7b7a6bd03b38cef55c86885fc6c1978b9cee7ef33da507c9df6b9277c" - "ff1e6aaa5d57aca528466102818100c931617c77829dfb1270502be9195c8f2830885f57dba869536811e6" - "864236d0c4736a0008a145af36b8357a7c3d139966d04c4e00934ea1aede3bb6b8ec841dc95e3f579751e2" - "bfdfe27ae778983f959356210723287b0affcc9f727044d48c373f1babde0724fa17a4fd4da0902c7c9b9b" - "f27ba61be6ad02dfddda8f4e6822"); - -string zero_masking_key = - hex2str("0000000000000000000000000000000000000000000000000000000000000000"); -string masking_key = hex2str("D796B02C370F1FA4CC0124F14EC8CBEBE987E825246265050F399A51FD477DFC"); - -class ImportWrappedKeyTest : public KeyMintAidlTestBase {}; - -TEST_P(ImportWrappedKeyTest, Success) { - auto wrapping_key_desc = AuthorizationSetBuilder() - .RsaEncryptionKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP) - .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY); - - ASSERT_EQ(ErrorCode::OK, - ImportWrappedKey(wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP))); - - string message = "Hello World!"; - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - string ciphertext = EncryptMessage(message, params); - string plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); -} - -TEST_P(ImportWrappedKeyTest, SuccessMasked) { - auto wrapping_key_desc = AuthorizationSetBuilder() - .RsaEncryptionKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP) - .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY); - - ASSERT_EQ(ErrorCode::OK, - ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, masking_key, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP))); -} - -TEST_P(ImportWrappedKeyTest, WrongMask) { - auto wrapping_key_desc = AuthorizationSetBuilder() - .RsaEncryptionKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP) - .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY); - - ASSERT_EQ( - ErrorCode::VERIFICATION_FAILED, - ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP))); -} - -TEST_P(ImportWrappedKeyTest, WrongPurpose) { - auto wrapping_key_desc = AuthorizationSetBuilder() - .RsaEncryptionKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP); - - ASSERT_EQ( - ErrorCode::INCOMPATIBLE_PURPOSE, - ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key, - AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP))); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(ImportWrappedKeyTest); - -typedef KeyMintAidlTestBase EncryptionOperationsTest; - -/* - * EncryptionOperationsTest.RsaNoPaddingSuccess - * - * Verifies that raw RSA encryption works. - */ -TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::NONE))); - - string message = string(2048 / 8, 'a'); - auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); - string ciphertext1 = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext1.size()); - - string ciphertext2 = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext2.size()); - - // Unpadded RSA is deterministic - EXPECT_EQ(ciphertext1, ciphertext2); -} - -/* - * EncryptionOperationsTest.RsaNoPaddingShortMessage - * - * Verifies that raw RSA encryption of short messages works. - */ -TEST_P(EncryptionOperationsTest, RsaNoPaddingShortMessage) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::NONE))); - - string message = "1"; - auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); - - string ciphertext = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext.size()); - - string expected_plaintext = string(2048U / 8 - 1, 0) + message; - string plaintext = DecryptMessage(ciphertext, params); - - EXPECT_EQ(expected_plaintext, plaintext); - - // Degenerate case, encrypting a numeric 1 yields 0x00..01 as the ciphertext. - message = static_cast<char>(1); - ciphertext = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext.size()); - EXPECT_EQ(ciphertext, string(2048U / 8 - 1, 0) + message); -} - -/* - * EncryptionOperationsTest.RsaNoPaddingTooLong - * - * Verifies that raw RSA encryption of too-long messages fails in the expected way. - */ -TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::NONE))); - - string message(2048 / 8 + 1, 'a'); - - auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params)); - - string result; - EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &result)); -} - -/* - * EncryptionOperationsTest.RsaNoPaddingTooLarge - * - * Verifies that raw RSA encryption of too-large (numerically) messages fails in the expected - * way. - */ -// TODO(seleneh) add RsaNoPaddingTooLarge test back after decided and implemented new -// version of ExportKey inside generateKey - -/* - * EncryptionOperationsTest.RsaOaepSuccess - * - * Verifies that RSA-OAEP encryption operations work, with all digests. - */ -TEST_P(EncryptionOperationsTest, RsaOaepSuccess) { - 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() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(key_size, 65537) - .Padding(PaddingMode::RSA_OAEP) - .Digest(digests))); - - string message = "Hello"; - - for (auto digest : digests) { - auto params = AuthorizationSetBuilder().Digest(digest).Padding(PaddingMode::RSA_OAEP); - string ciphertext1 = EncryptMessage(message, params); - if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl; - EXPECT_EQ(key_size / 8, ciphertext1.size()); - - string ciphertext2 = EncryptMessage(message, params); - EXPECT_EQ(key_size / 8, ciphertext2.size()); - - // OAEP randomizes padding so every result should be different (with astronomically high - // probability). - EXPECT_NE(ciphertext1, ciphertext2); - - string plaintext1 = DecryptMessage(ciphertext1, params); - EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest; - string plaintext2 = DecryptMessage(ciphertext2, params); - EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest; - - // Decrypting corrupted ciphertext should fail. - size_t offset_to_corrupt = random() % ciphertext1.size(); - char corrupt_byte; - do { - corrupt_byte = static_cast<char>(random() % 256); - } while (corrupt_byte == ciphertext1[offset_to_corrupt]); - ciphertext1[offset_to_corrupt] = corrupt_byte; - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - string result; - EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result)); - EXPECT_EQ(0U, result.size()); - } -} - -/* - * EncryptionOperationsTest.RsaOaepInvalidDigest - * - * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate - * without a digest. - */ -TEST_P(EncryptionOperationsTest, RsaOaepInvalidDigest) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::RSA_OAEP) - .Digest(Digest::NONE))); - string message = "Hello World!"; - - auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::NONE); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_DIGEST, Begin(KeyPurpose::ENCRYPT, params)); -} - -/* - * EncryptionOperationsTest.RsaOaepInvalidDigest - * - * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to decrypt - * with a different digest than was used to encrypt. - */ -TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(1024, 65537) - .Padding(PaddingMode::RSA_OAEP) - .Digest(Digest::SHA_2_224, Digest::SHA_2_256))); - string message = "Hello World!"; - string ciphertext = EncryptMessage( - message, - AuthorizationSetBuilder().Digest(Digest::SHA_2_224).Padding(PaddingMode::RSA_OAEP)); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_OAEP))); - string result; - EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext, &result)); - EXPECT_EQ(0U, result.size()); -} - -/* - * EncryptionOperationsTest.RsaOaepTooLarge - * - * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to encrypt a - * too-large message. - */ -TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::RSA_OAEP) - .Digest(Digest::SHA_2_256))); - constexpr size_t digest_size = 256 /* SHA_2_256 */ / 8; - constexpr size_t oaep_overhead = 2 * digest_size + 2; - string message(2048 / 8 - oaep_overhead + 1, 'a'); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, AuthorizationSetBuilder() - .Padding(PaddingMode::RSA_OAEP) - .Digest(Digest::SHA_2_256))); - string result; - ErrorCode error = Finish(message, &result); - EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT); - EXPECT_EQ(0U, result.size()); -} - -/* - * EncryptionOperationsTest.RsaPkcs1Success - * - * Verifies that RSA PKCS encryption/decrypts works. - */ -TEST_P(EncryptionOperationsTest, RsaPkcs1Success) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT))); - - string message = "Hello World!"; - auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT); - string ciphertext1 = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext1.size()); - - string ciphertext2 = EncryptMessage(message, params); - EXPECT_EQ(2048U / 8, ciphertext2.size()); - - // PKCS1 v1.5 randomizes padding so every result should be different. - EXPECT_NE(ciphertext1, ciphertext2); - - string plaintext = DecryptMessage(ciphertext1, params); - EXPECT_EQ(message, plaintext); - - // Decrypting corrupted ciphertext should fail. - size_t offset_to_corrupt = random() % ciphertext1.size(); - char corrupt_byte; - do { - corrupt_byte = static_cast<char>(random() % 256); - } while (corrupt_byte == ciphertext1[offset_to_corrupt]); - ciphertext1[offset_to_corrupt] = corrupt_byte; - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - string result; - EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result)); - EXPECT_EQ(0U, result.size()); -} - -/* - * EncryptionOperationsTest.RsaPkcs1TooLarge - * - * Verifies that RSA PKCS encryption fails in the correct way when the mssage is too large. - */ -TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT))); - string message(2048 / 8 - 10, 'a'); - - auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params)); - string result; - ErrorCode error = Finish(message, &result); - EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT); - EXPECT_EQ(0U, result.size()); -} - -/* - * EncryptionOperationsTest.EcdsaEncrypt - * - * Verifies that attempting to use ECDSA keys to encrypt fails in the correct way. - */ -TEST_P(EncryptionOperationsTest, EcdsaEncrypt) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) - .Digest(Digest::NONE))); - auto params = AuthorizationSetBuilder().Digest(Digest::NONE); - ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params)); - ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params)); -} - -/* - * EncryptionOperationsTest.HmacEncrypt - * - * Verifies that attempting to use HMAC keys to encrypt fails in the correct way. - */ -TEST_P(EncryptionOperationsTest, HmacEncrypt) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .HmacKey(128) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - auto params = AuthorizationSetBuilder() - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params)); - ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params)); -} - -/* - * EncryptionOperationsTest.AesEcbRoundTripSuccess - * - * Verifies that AES ECB mode works. - */ -TEST_P(EncryptionOperationsTest, AesEcbRoundTripSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB) - .Padding(PaddingMode::NONE))); - - ASSERT_GT(key_blob_.size(), 0U); - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE); - - // Two-block message. - string message = "12345678901234567890123456789012"; - string ciphertext1 = EncryptMessage(message, params); - EXPECT_EQ(message.size(), ciphertext1.size()); - - string ciphertext2 = EncryptMessage(string(message), params); - EXPECT_EQ(message.size(), ciphertext2.size()); - - // ECB is deterministic. - EXPECT_EQ(ciphertext1, ciphertext2); - - string plaintext = DecryptMessage(ciphertext1, params); - EXPECT_EQ(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesEcbRoundTripSuccess - * - * Verifies that AES encryption fails in the correct way when an unauthorized mode is specified. - */ -TEST_P(EncryptionOperationsTest, AesWrongMode) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CBC) - .Padding(PaddingMode::NONE))); - - ASSERT_GT(key_blob_.size(), 0U); - - // Two-block message. - string message = "12345678901234567890123456789012"; - EXPECT_EQ( - ErrorCode::INCOMPATIBLE_BLOCK_MODE, - Begin(KeyPurpose::ENCRYPT, - 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_P(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; - ASSERT_GT(key_blob_.size(), 0U); - - err = Begin(KeyPurpose::DECRYPT, AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128)); - 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) - .Authorization(TAG_MAC_LENGTH, 128)); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err; -} - -/* - * EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize - * - * Verifies that AES encryption fails in the correct way when provided an input that is not a - * multiple of the block size and no padding is specified. - */ -TEST_P(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB) - .Padding(PaddingMode::NONE))); - // Message is slightly shorter than two blocks. - string message(16 * 2 - 1, 'a'); - - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params)); - string ciphertext; - EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &ciphertext)); - EXPECT_EQ(0U, ciphertext.size()); -} - -/* - * EncryptionOperationsTest.AesEcbPkcs7Padding - * - * Verifies that AES PKCS7 padding works for any message length. - */ -TEST_P(EncryptionOperationsTest, AesEcbPkcs7Padding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB) - .Padding(PaddingMode::PKCS7))); - - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - - // Try various message lengths; all should work. - for (size_t i = 0; i < 32; ++i) { - string message(i, 'a'); - string ciphertext = EncryptMessage(message, params); - EXPECT_EQ(i + 16 - (i % 16), ciphertext.size()); - string plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); - } -} - -/* - * EncryptionOperationsTest.AesEcbWrongPadding - * - * Verifies that AES enryption fails in the correct way when an unauthorized padding mode is - * specified. - */ -TEST_P(EncryptionOperationsTest, AesEcbWrongPadding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB) - .Padding(PaddingMode::NONE))); - - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - - // Try various message lengths; all should fail - for (size_t i = 0; i < 32; ++i) { - string message(i, 'a'); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params)); - } -} - -/* - * EncryptionOperationsTest.AesEcbPkcs7PaddingCorrupted - * - * Verifies that AES decryption fails in the correct way when the padding is corrupted. - */ -TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::ECB) - .Padding(PaddingMode::PKCS7))); - - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - - string message = "a"; - string ciphertext = EncryptMessage(message, params); - EXPECT_EQ(16U, ciphertext.size()); - EXPECT_NE(ciphertext, message); - ++ciphertext[ciphertext.size() / 2]; - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - string plaintext; - EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext)); -} - -vector<uint8_t> CopyIv(const AuthorizationSet& set) { - auto iv = set.GetTagValue(TAG_NONCE); - EXPECT_TRUE(iv.isOk()); - return iv.value(); -} - -/* - * EncryptionOperationsTest.AesCtrRoundTripSuccess - * - * Verifies that AES CTR mode works. - */ -TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CTR) - .Padding(PaddingMode::NONE))); - - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE); - - string message = "123"; - AuthorizationSet out_params; - string ciphertext1 = EncryptMessage(message, params, &out_params); - vector<uint8_t> iv1 = CopyIv(out_params); - EXPECT_EQ(16U, iv1.size()); - - EXPECT_EQ(message.size(), ciphertext1.size()); - - out_params.Clear(); - string ciphertext2 = EncryptMessage(message, params, &out_params); - vector<uint8_t> iv2 = CopyIv(out_params); - EXPECT_EQ(16U, iv2.size()); - - // IVs should be random, so ciphertexts should differ. - EXPECT_NE(ciphertext1, ciphertext2); - - auto params_iv1 = - AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv1); - auto params_iv2 = - AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv2); - - string plaintext = DecryptMessage(ciphertext1, params_iv1); - EXPECT_EQ(message, plaintext); - plaintext = DecryptMessage(ciphertext2, params_iv2); - EXPECT_EQ(message, plaintext); - - // Using the wrong IV will result in a "valid" decryption, but the data will be garbage. - plaintext = DecryptMessage(ciphertext1, params_iv2); - EXPECT_NE(message, plaintext); - plaintext = DecryptMessage(ciphertext2, params_iv1); - EXPECT_NE(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesIncremental - * - * Verifies that AES works, all modes, when provided data in various size increments. - */ -TEST_P(EncryptionOperationsTest, AesIncremental) { - auto block_modes = { - BlockMode::ECB, - BlockMode::CBC, - BlockMode::CTR, - BlockMode::GCM, - }; - - 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))); - - 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 */; - - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params)); - - string ciphertext; - int32_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; - } - } - } -} - -struct AesCtrSp80038aTestVector { - const char* key; - const char* nonce; - const char* plaintext; - const char* ciphertext; -}; - -// These test vectors are taken from -// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section F.5. -static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = { - // AES-128 - { - "2b7e151628aed2a6abf7158809cf4f3c", - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51" - "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", - "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff" - "5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee", - }, - // AES-192 - { - "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51" - "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", - "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94" - "1e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050", - }, - // AES-256 - { - "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51" - "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", - "601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5" - "2b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6", - }, -}; - -/* - * EncryptionOperationsTest.AesCtrSp80038aTestVector - * - * Verifies AES CTR implementation against SP800-38A test vectors. - */ -TEST_P(EncryptionOperationsTest, AesCtrSp80038aTestVector) { - std::vector<uint32_t> InvalidSizes = InvalidKeySizes(Algorithm::AES); - for (size_t i = 0; i < 3; i++) { - const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]); - const string key = hex2str(test.key); - if (std::find(InvalidSizes.begin(), InvalidSizes.end(), (key.size() * 8)) != - InvalidSizes.end()) - continue; - const string nonce = hex2str(test.nonce); - const string plaintext = hex2str(test.plaintext); - const string ciphertext = hex2str(test.ciphertext); - CheckAesCtrTestVector(key, nonce, plaintext, ciphertext); - } -} - -/* - * EncryptionOperationsTest.AesCtrIncompatiblePaddingMode - * - * Verifies that keymint rejects use of CTR mode with PKCS7 padding in the correct way. - */ -TEST_P(EncryptionOperationsTest, AesCtrIncompatiblePaddingMode) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CTR) - .Padding(PaddingMode::PKCS7))); - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params)); -} - -/* - * EncryptionOperationsTest.AesCtrInvalidCallerNonce - * - * Verifies that keymint fails correctly when the user supplies an incorrect-size nonce. - */ -TEST_P(EncryptionOperationsTest, AesCtrInvalidCallerNonce) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CTR) - .Authorization(TAG_CALLER_NONCE) - .Padding(PaddingMode::NONE))); - - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CTR) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf(string(1, 'a'))); - EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params)); - - params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CTR) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf(string(15, 'a'))); - EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params)); - - params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CTR) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf(string(17, 'a'))); - EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params)); -} - -/* - * EncryptionOperationsTest.AesCtrInvalidCallerNonce - * - * Verifies that keymint fails correctly when the user supplies an incorrect-size nonce. - */ -TEST_P(EncryptionOperationsTest, AesCbcRoundTripSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CBC) - .Padding(PaddingMode::NONE))); - // Two-block message. - string message = "12345678901234567890123456789012"; - auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - AuthorizationSet out_params; - string ciphertext1 = EncryptMessage(message, params, &out_params); - vector<uint8_t> iv1 = CopyIv(out_params); - EXPECT_EQ(message.size(), ciphertext1.size()); - - out_params.Clear(); - - string ciphertext2 = EncryptMessage(message, params, &out_params); - vector<uint8_t> iv2 = CopyIv(out_params); - EXPECT_EQ(message.size(), ciphertext2.size()); - - // IVs should be random, so ciphertexts should differ. - EXPECT_NE(ciphertext1, ciphertext2); - - params.push_back(TAG_NONCE, iv1); - string plaintext = DecryptMessage(ciphertext1, params); - EXPECT_EQ(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesCallerNonce - * - * Verifies that AES caller-provided nonces work correctly. - */ -TEST_P(EncryptionOperationsTest, AesCallerNonce) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CBC) - .Authorization(TAG_CALLER_NONCE) - .Padding(PaddingMode::NONE))); - - string message = "12345678901234567890123456789012"; - - // Don't specify nonce, should get a random one. - AuthorizationSetBuilder params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - AuthorizationSet out_params; - string ciphertext = EncryptMessage(message, params, &out_params); - EXPECT_EQ(message.size(), ciphertext.size()); - EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size()); - - params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value()); - string plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); - - // Now specify a nonce, should also work. - params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CBC) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf("abcdefghijklmnop")); - out_params.Clear(); - ciphertext = EncryptMessage(message, params, &out_params); - - // Decrypt with correct nonce. - plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); - - // Try with wrong nonce. - params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CBC) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf("aaaaaaaaaaaaaaaa")); - plaintext = DecryptMessage(ciphertext, params); - EXPECT_NE(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesCallerNonceProhibited - * - * Verifies that caller-provided nonces are not permitted when not specified in the key - * authorizations. - */ -TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .Authorization(TAG_BLOCK_MODE, BlockMode::CBC) - .Padding(PaddingMode::NONE))); - - string message = "12345678901234567890123456789012"; - - // Don't specify nonce, should get a random one. - AuthorizationSetBuilder params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - AuthorizationSet out_params; - string ciphertext = EncryptMessage(message, params, &out_params); - EXPECT_EQ(message.size(), ciphertext.size()); - EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size()); - - params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value()); - string plaintext = DecryptMessage(ciphertext, params); - EXPECT_EQ(message, plaintext); - - // Now specify a nonce, should fail - params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CBC) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NONCE, AidlBuf("abcdefghijklmnop")); - out_params.Clear(); - EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED, Begin(KeyPurpose::ENCRYPT, params, &out_params)); -} - -/* - * EncryptionOperationsTest.AesGcmRoundTripSuccess - * - * Verifies that AES GCM mode works. - */ -TEST_P(EncryptionOperationsTest, AesGcmRoundTripSuccess) { - 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; - ASSERT_EQ(ErrorCode::OK, Finish(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; - int32_t input_consumed; - ASSERT_EQ(ErrorCode::OK, - Update(update_params, ciphertext, &update_out_params, &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); -} - -/* - * EncryptionOperationsTest.AesGcmRoundTripWithDelaySuccess - * - * Verifies that AES GCM mode works, even when there's a long delay - * between operations. - */ -TEST_P(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(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; - int32_t input_consumed; - sleep(5); - ASSERT_EQ(ErrorCode::OK, - Update(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_P(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, AidlBuf(nonce1)); - string ciphertext2 = - EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, AidlBuf(nonce2)); - string ciphertext3 = - EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, AidlBuf(nonce3)); - - ASSERT_NE(ciphertext1, ciphertext2); - ASSERT_NE(ciphertext1, ciphertext3); - ASSERT_NE(ciphertext2, ciphertext3); -} - -/* - * EncryptionOperationsTest.AesGcmTooShortTag - * - * Verifies that AES GCM mode fails correctly when a too-short tag length is specified. - */ -TEST_P(EncryptionOperationsTest, AesGcmTooShortTag) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - string message = "123456789012345678901234567890123456"; - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 96); - - EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::ENCRYPT, params)); -} - -/* - * EncryptionOperationsTest.AesGcmTooShortTagOnDecrypt - * - * Verifies that AES GCM mode fails correctly when a too-short tag is provided to decryption. - */ -TEST_P(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - string aad = "foobar"; - string message = "123456789012345678901234567890123456"; - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - - auto finish_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size()); - - // Encrypt - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params)); - EXPECT_EQ(1U, begin_out_params.size()); - ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk()); - - AuthorizationSet finish_out_params; - string ciphertext; - EXPECT_EQ(ErrorCode::OK, - Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext)); - - params = AuthorizationSetBuilder() - .Authorizations(begin_out_params) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 96); - - // Decrypt. - EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::DECRYPT, params)); -} - -/* - * EncryptionOperationsTest.AesGcmCorruptKey - * - * Verifies that AES GCM mode fails correctly when the decryption key is incorrect. - */ -TEST_P(EncryptionOperationsTest, AesGcmCorruptKey) { - const uint8_t nonce_bytes[] = { - 0xb7, 0x94, 0x37, 0xae, 0x08, 0xff, 0x35, 0x5d, 0x7d, 0x8a, 0x4d, 0x0f, - }; - string nonce = make_string(nonce_bytes); - const uint8_t ciphertext_bytes[] = { - 0xb3, 0xf6, 0x79, 0x9e, 0x8f, 0x93, 0x26, 0xf2, 0xdf, 0x1e, 0x80, 0xfc, - 0xd2, 0xcb, 0x16, 0xd7, 0x8c, 0x9d, 0xc7, 0xcc, 0x14, 0xbb, 0x67, 0x78, - 0x62, 0xdc, 0x6c, 0x63, 0x9b, 0x3a, 0x63, 0x38, 0xd2, 0x4b, 0x31, 0x2d, - 0x39, 0x89, 0xe5, 0x92, 0x0b, 0x5d, 0xbf, 0xc9, 0x76, 0x76, 0x5e, 0xfb, - 0xfe, 0x57, 0xbb, 0x38, 0x59, 0x40, 0xa7, 0xa4, 0x3b, 0xdf, 0x05, 0xbd, - 0xda, 0xe3, 0xc9, 0xd6, 0xa2, 0xfb, 0xbd, 0xfc, 0xc0, 0xcb, 0xa0, - }; - string ciphertext = make_string(ciphertext_bytes); - - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128) - .Authorization(TAG_NONCE, nonce.data(), nonce.size()); - - auto import_params = AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_CALLER_NONCE) - .Authorization(TAG_MIN_MAC_LENGTH, 128); - - // Import correct key and decrypt - const uint8_t key_bytes[] = { - 0xba, 0x76, 0x35, 0x4f, 0x0a, 0xed, 0x6e, 0x8d, - 0x91, 0xf4, 0x5c, 0x4f, 0xf5, 0xa0, 0x62, 0xdb, - }; - string key = make_string(key_bytes); - ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key)); - string plaintext = DecryptMessage(ciphertext, params); - CheckedDeleteKey(); - - // Corrupt key and attempt to decrypt - key[0] = 0; - ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key)); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext)); - CheckedDeleteKey(); -} - -/* - * EncryptionOperationsTest.AesGcmAadNoData - * - * Verifies that AES GCM mode works when provided additional authenticated data, but no data to - * encrypt. - */ -TEST_P(EncryptionOperationsTest, AesGcmAadNoData) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string aad = "1234567890123456"; - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - - auto finish_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size()); - - // Encrypt - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params)); - string ciphertext; - AuthorizationSet finish_out_params; - EXPECT_EQ(ErrorCode::OK, Finish(finish_params, "" /* input */, "" /* signature */, - &finish_out_params, &ciphertext)); - EXPECT_TRUE(finish_out_params.empty()); - - // Grab nonce - params.push_back(begin_out_params); - - // Decrypt. - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - string plaintext; - EXPECT_EQ(ErrorCode::OK, Finish(finish_params, ciphertext, "" /* signature */, - &finish_out_params, &plaintext)); - - EXPECT_TRUE(finish_out_params.empty()); - - EXPECT_EQ("", plaintext); -} - -/* - * EncryptionOperationsTest.AesGcmMultiPartAad - * - * Verifies that AES GCM mode works when provided additional authenticated data in multiple - * chunks. - */ -TEST_P(EncryptionOperationsTest, AesGcmMultiPartAad) { - const size_t tag_bits = 128; - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string message = "123456789012345678901234567890123456"; - auto begin_params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, tag_bits); - AuthorizationSet begin_out_params; - - auto update_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params)); - - // No data, AAD only. - string ciphertext; - int32_t input_consumed; - AuthorizationSet update_out_params; - EXPECT_EQ(ErrorCode::OK, Update(update_params, "" /* input */, &update_out_params, &ciphertext, - &input_consumed)); - EXPECT_EQ(0U, input_consumed); - EXPECT_EQ(0U, ciphertext.size()); - EXPECT_TRUE(update_out_params.empty()); - - // AAD and data. - EXPECT_EQ(ErrorCode::OK, - Update(update_params, message, &update_out_params, &ciphertext, &input_consumed)); - EXPECT_EQ(message.size(), input_consumed); - EXPECT_TRUE(update_out_params.empty()); - - EXPECT_EQ(ErrorCode::OK, Finish("" /* input */, &ciphertext)); - // Expect 128-bit (16-byte) tag appended to ciphertext. - EXPECT_EQ(message.size() + (tag_bits >> 3), ciphertext.size()); - - // Grab nonce. - begin_params.push_back(begin_out_params); - - // Decrypt - update_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foofoo", (size_t)6); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)); - string plaintext; - EXPECT_EQ(ErrorCode::OK, Finish(update_params, ciphertext, "" /* signature */, - &update_out_params, &plaintext)); - EXPECT_TRUE(update_out_params.empty()); - EXPECT_EQ(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesGcmAadOutOfOrder - * - * Verifies that AES GCM mode fails correctly when given AAD after data to encipher. - */ -TEST_P(EncryptionOperationsTest, AesGcmAadOutOfOrder) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string message = "123456789012345678901234567890123456"; - auto begin_params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - AuthorizationSet begin_out_params; - - auto update_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params)); - - // No data, AAD only. - string ciphertext; - int32_t input_consumed; - AuthorizationSet update_out_params; - EXPECT_EQ(ErrorCode::OK, Update(update_params, "" /* input */, &update_out_params, &ciphertext, - &input_consumed)); - EXPECT_EQ(0U, input_consumed); - EXPECT_EQ(0U, ciphertext.size()); - EXPECT_TRUE(update_out_params.empty()); - - // AAD and data. - EXPECT_EQ(ErrorCode::OK, - Update(update_params, message, &update_out_params, &ciphertext, &input_consumed)); - EXPECT_EQ(message.size(), input_consumed); - EXPECT_TRUE(update_out_params.empty()); - - // More AAD - EXPECT_EQ(ErrorCode::INVALID_TAG, - Update(update_params, "", &update_out_params, &ciphertext, &input_consumed)); - - op_.clear(); -} - -/* - * EncryptionOperationsTest.AesGcmBadAad - * - * Verifies that AES GCM decryption fails correctly when additional authenticated date is wrong. - */ -TEST_P(EncryptionOperationsTest, AesGcmBadAad) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string message = "12345678901234567890123456789012"; - auto begin_params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - - auto finish_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6); - - // Encrypt - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params)); - string ciphertext; - AuthorizationSet finish_out_params; - EXPECT_EQ(ErrorCode::OK, - Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext)); - - // Grab nonce - begin_params.push_back(begin_out_params); - - finish_params = AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, - "barfoo" /* Wrong AAD */, (size_t)6); - - // Decrypt. - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params)); - string plaintext; - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */, - &finish_out_params, &plaintext)); -} - -/* - * EncryptionOperationsTest.AesGcmWrongNonce - * - * Verifies that AES GCM decryption fails correctly when the nonce is incorrect. - */ -TEST_P(EncryptionOperationsTest, AesGcmWrongNonce) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string message = "12345678901234567890123456789012"; - auto begin_params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - - auto finish_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6); - - // Encrypt - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params)); - string ciphertext; - AuthorizationSet finish_out_params; - EXPECT_EQ(ErrorCode::OK, - Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext)); - - // Wrong nonce - begin_params.push_back(TAG_NONCE, AidlBuf("123456789012")); - - // Decrypt. - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params)); - string plaintext; - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */, - &finish_out_params, &plaintext)); - - // With wrong nonce, should have gotten garbage plaintext (or none). - EXPECT_NE(message, plaintext); -} - -/* - * EncryptionOperationsTest.AesGcmCorruptTag - * - * Verifies that AES GCM decryption fails correctly when the tag is wrong. - */ -TEST_P(EncryptionOperationsTest, AesGcmCorruptTag) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, 128))); - - string aad = "1234567890123456"; - string message = "123456789012345678901234567890123456"; - - auto params = AuthorizationSetBuilder() - .BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, 128); - - auto finish_params = - AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size()); - - // Encrypt - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params)); - string ciphertext; - AuthorizationSet finish_out_params; - EXPECT_EQ(ErrorCode::OK, - Finish(finish_params, message, "" /* signature */, &finish_out_params, &ciphertext)); - EXPECT_TRUE(finish_out_params.empty()); - - // Corrupt tag - ++(*ciphertext.rbegin()); - - // Grab nonce - params.push_back(begin_out_params); - - // Decrypt. - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params)); - string plaintext; - EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(finish_params, ciphertext, "" /* signature */, - &finish_out_params, &plaintext)); - EXPECT_TRUE(finish_out_params.empty()); -} - -/* - * EncryptionOperationsTest.TripleDesEcbRoundTripSuccess - * - * Verifies that 3DES is basically functional. - */ -TEST_P(EncryptionOperationsTest, TripleDesEcbRoundTripSuccess) { - auto auths = AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::ECB) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE); - - ASSERT_EQ(ErrorCode::OK, GenerateKey(auths)); - // Two-block message. - string message = "1234567890123456"; - auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE); - string ciphertext1 = EncryptMessage(message, inParams); - EXPECT_EQ(message.size(), ciphertext1.size()); - - string ciphertext2 = EncryptMessage(string(message), inParams); - EXPECT_EQ(message.size(), ciphertext2.size()); - - // ECB is deterministic. - EXPECT_EQ(ciphertext1, ciphertext2); - - string plaintext = DecryptMessage(ciphertext1, inParams); - EXPECT_EQ(message, plaintext); -} - -/* - * EncryptionOperationsTest.TripleDesEcbNotAuthorized - * - * Verifies that CBC keys reject ECB usage. - */ -TEST_P(EncryptionOperationsTest, TripleDesEcbNotAuthorized) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - auto inParams = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, inParams)); -} - -/* - * EncryptionOperationsTest.TripleDesEcbPkcs7Padding - * - * Tests ECB mode with PKCS#7 padding, various message sizes. - */ -TEST_P(EncryptionOperationsTest, TripleDesEcbPkcs7Padding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::ECB) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::PKCS7))); - - for (size_t i = 0; i < 32; ++i) { - string message(i, 'a'); - auto inParams = - AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - string ciphertext = EncryptMessage(message, inParams); - EXPECT_EQ(i + 8 - (i % 8), ciphertext.size()); - string plaintext = DecryptMessage(ciphertext, inParams); - EXPECT_EQ(message, plaintext); - } -} - -/* - * EncryptionOperationsTest.TripleDesEcbNoPaddingKeyWithPkcs7Padding - * - * Verifies that keys configured for no padding reject PKCS7 padding - */ -TEST_P(EncryptionOperationsTest, TripleDesEcbNoPaddingKeyWithPkcs7Padding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::ECB) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - for (size_t i = 0; i < 32; ++i) { - auto inParams = - AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, inParams)); - } -} - -/* - * EncryptionOperationsTest.TripleDesEcbPkcs7PaddingCorrupted - * - * Verifies that corrupted padding is detected. - */ -TEST_P(EncryptionOperationsTest, TripleDesEcbPkcs7PaddingCorrupted) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::ECB) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::PKCS7))); - - string message = "a"; - string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7); - EXPECT_EQ(8U, ciphertext.size()); - EXPECT_NE(ciphertext, message); - ++ciphertext[ciphertext.size() / 2]; - - AuthorizationSetBuilder begin_params; - begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB); - begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)); - string plaintext; - int32_t input_consumed; - EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed)); - EXPECT_EQ(ciphertext.size(), input_consumed); - EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext)); -} - -struct TripleDesTestVector { - const char* name; - const KeyPurpose purpose; - const BlockMode block_mode; - const PaddingMode padding_mode; - const char* key; - const char* iv; - const char* input; - const char* output; -}; - -// These test vectors are from NIST CAVP, plus a few custom variants to test padding, since all -// of the NIST vectors are multiples of the block size. -static const TripleDesTestVector kTripleDesTestVectors[] = { - { - "TECBMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE, - "a2b5bc67da13dc92cd9d344aa238544a0e1fa79ef76810cd", // key - "", // IV - "329d86bdf1bc5af4", // input - "d946c2756d78633f", // output - }, - { - "TECBMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::ECB, PaddingMode::NONE, - "49e692290d2a5e46bace79b9648a4c5d491004c262dc9d49", // key - "", // IV - "6b1540781b01ce1997adae102dbf3c5b", // input - "4d0dc182d6e481ac4a3dc6ab6976ccae", // output - }, - { - "TECBMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE, - "52daec2ac7dc1958377392682f37860b2cc1ea2304bab0e9", // key - "", // IV - "6daad94ce08acfe7", // input - "660e7d32dcc90e79", // output - }, - { - "TECBMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::ECB, PaddingMode::NONE, - "7f8fe3d3f4a48394fb682c2919926d6ddfce8932529229ce", // key - "", // IV - "e9653a0a1f05d31b9acd12d73aa9879d", // input - "9b2ae9d998efe62f1b592e7e1df8ff38", // output - }, - { - "TCBCMMT3 Encrypt 0", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE, - "b5cb1504802326c73df186e3e352a20de643b0d63ee30e37", // key - "43f791134c5647ba", // IV - "dcc153cef81d6f24", // input - "92538bd8af18d3ba", // output - }, - { - "TCBCMMT3 Encrypt 1", KeyPurpose::ENCRYPT, BlockMode::CBC, PaddingMode::NONE, - "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key - "c2e999cb6249023c", // IV - "c689aee38a301bb316da75db36f110b5", // input - "e9afaba5ec75ea1bbe65506655bb4ecb", // output - }, - { - "TCBCMMT3 Encrypt 1 PKCS7 variant", KeyPurpose::ENCRYPT, BlockMode::CBC, - PaddingMode::PKCS7, - "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key - "c2e999cb6249023c", // IV - "c689aee38a301bb316da75db36f110b500", // input - "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156", // output - }, - { - "TCBCMMT3 Encrypt 1 PKCS7 decrypted", KeyPurpose::DECRYPT, BlockMode::CBC, - PaddingMode::PKCS7, - "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358", // key - "c2e999cb6249023c", // IV - "e9afaba5ec75ea1bbe65506655bb4ecb825aa27ec0656156", // input - "c689aee38a301bb316da75db36f110b500", // output - }, - { - "TCBCMMT3 Decrypt 0", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE, - "5eb6040d46082c7aa7d06dfd08dfeac8c18364c1548c3ba1", // key - "41746c7e442d3681", // IV - "c53a7b0ec40600fe", // input - "d4f00eb455de1034", // output - }, - { - "TCBCMMT3 Decrypt 1", KeyPurpose::DECRYPT, BlockMode::CBC, PaddingMode::NONE, - "5b1cce7c0dc1ec49130dfb4af45785ab9179e567f2c7d549", // key - "3982bc02c3727d45", // IV - "6006f10adef52991fcc777a1238bbb65", // input - "edae09288e9e3bc05746d872b48e3b29", // output - }, -}; - -/* - * EncryptionOperationsTest.TripleDesTestVector - * - * Verifies that NIST (plus a few extra) test vectors produce the correct results. - */ -TEST_P(EncryptionOperationsTest, TripleDesTestVector) { - constexpr size_t num_tests = sizeof(kTripleDesTestVectors) / sizeof(TripleDesTestVector); - for (auto* test = kTripleDesTestVectors; test < kTripleDesTestVectors + num_tests; ++test) { - SCOPED_TRACE(test->name); - CheckTripleDesTestVector(test->purpose, test->block_mode, test->padding_mode, - hex2str(test->key), hex2str(test->iv), hex2str(test->input), - hex2str(test->output)); - } -} - -/* - * EncryptionOperationsTest.TripleDesCbcRoundTripSuccess - * - * Validates CBC mode functionality. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcRoundTripSuccess) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - ASSERT_GT(key_blob_.size(), 0U); - - // Two-block message. - string message = "1234567890123456"; - vector<uint8_t> iv1; - string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv1); - EXPECT_EQ(message.size(), ciphertext1.size()); - - vector<uint8_t> iv2; - string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv2); - EXPECT_EQ(message.size(), ciphertext2.size()); - - // IVs should be random, so ciphertexts should differ. - EXPECT_NE(iv1, iv2); - EXPECT_NE(ciphertext1, ciphertext2); - - string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv1); - EXPECT_EQ(message, plaintext); -} - -/* - * EncryptionOperationsTest.TripleDesCallerIv - * - * Validates that 3DES keys can allow caller-specified IVs, and use them correctly. - */ -TEST_P(EncryptionOperationsTest, TripleDesCallerIv) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_CALLER_NONCE) - .Padding(PaddingMode::NONE))); - string message = "1234567890123456"; - vector<uint8_t> iv; - // Don't specify IV, should get a random one. - string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv); - EXPECT_EQ(message.size(), ciphertext1.size()); - EXPECT_EQ(8U, iv.size()); - - string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv); - EXPECT_EQ(message, plaintext); - - // Now specify an IV, should also work. - iv = AidlBuf("abcdefgh"); - string ciphertext2 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, iv); - - // Decrypt with correct IV. - plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, iv); - EXPECT_EQ(message, plaintext); - - // Now try with wrong IV. - plaintext = DecryptMessage(ciphertext2, BlockMode::CBC, PaddingMode::NONE, AidlBuf("aaaaaaaa")); - EXPECT_NE(message, plaintext); -} - -/* - * EncryptionOperationsTest, TripleDesCallerNonceProhibited. - * - * Verifies that 3DES keys without TAG_CALLER_NONCE do not allow caller-specified IVS. - */ -TEST_P(EncryptionOperationsTest, TripleDesCallerNonceProhibited) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - string message = "12345678901234567890123456789012"; - vector<uint8_t> iv; - // Don't specify nonce, should get a random one. - string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv); - EXPECT_EQ(message.size(), ciphertext1.size()); - EXPECT_EQ(8U, iv.size()); - - string plaintext = DecryptMessage(ciphertext1, BlockMode::CBC, PaddingMode::NONE, iv); - EXPECT_EQ(message, plaintext); - - // Now specify a nonce, should fail. - auto input_params = AuthorizationSetBuilder() - .Authorization(TAG_NONCE, AidlBuf("abcdefgh")) - .BlockMode(BlockMode::CBC) - .Padding(PaddingMode::NONE); - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED, - Begin(KeyPurpose::ENCRYPT, input_params, &output_params)); -} - -/* - * EncryptionOperationsTest.TripleDesCbcNotAuthorized - * - * Verifies that 3DES ECB-only keys do not allow CBC usage. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcNotAuthorized) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::ECB) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - // Two-block message. - string message = "1234567890123456"; - auto begin_params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_BLOCK_MODE, Begin(KeyPurpose::ENCRYPT, begin_params)); -} - -/* - * EncryptionOperationsTest.TripleDesCbcNoPaddingWrongInputSize - * - * Verifies that unpadded CBC operations reject inputs that are not a multiple of block size. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcNoPaddingWrongInputSize) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - // Message is slightly shorter than two blocks. - string message = "123456789012345"; - - auto begin_params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &output_params)); - string ciphertext; - EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, "", &ciphertext)); -} - -/* - * EncryptionOperationsTest, TripleDesCbcPkcs7Padding. - * - * Verifies that PKCS7 padding works correctly in CBC mode. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcPkcs7Padding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::PKCS7))); - - // Try various message lengths; all should work. - for (size_t i = 0; i < 32; ++i) { - string message(i, 'a'); - vector<uint8_t> iv; - string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv); - EXPECT_EQ(i + 8 - (i % 8), ciphertext.size()); - string plaintext = DecryptMessage(ciphertext, BlockMode::CBC, PaddingMode::PKCS7, iv); - EXPECT_EQ(message, plaintext); - } -} - -/* - * EncryptionOperationsTest.TripleDesCbcNoPaddingKeyWithPkcs7Padding - * - * Verifies that a key that requires PKCS7 padding cannot be used in unpadded mode. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcNoPaddingKeyWithPkcs7Padding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - // Try various message lengths; all should fail. - for (size_t i = 0; i < 32; ++i) { - auto begin_params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::PKCS7); - EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, begin_params)); - } -} - -/* - * EncryptionOperationsTest.TripleDesCbcPkcs7PaddingCorrupted - * - * Verifies that corrupted PKCS7 padding is rejected during decryption. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcPkcs7PaddingCorrupted) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::PKCS7))); - - string message = "a"; - vector<uint8_t> iv; - string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv); - EXPECT_EQ(8U, ciphertext.size()); - EXPECT_NE(ciphertext, message); - ++ciphertext[ciphertext.size() / 2]; - - auto begin_params = AuthorizationSetBuilder() - .BlockMode(BlockMode::CBC) - .Padding(PaddingMode::PKCS7) - .Authorization(TAG_NONCE, iv); - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)); - string plaintext; - int32_t input_consumed; - EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed)); - EXPECT_EQ(ciphertext.size(), input_consumed); - EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext)); -} - -/* - * EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding. - * - * Verifies that 3DES CBC works with many different input sizes. - */ -TEST_P(EncryptionOperationsTest, TripleDesCbcIncrementalNoPadding) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .TripleDesEncryptionKey(168) - .BlockMode(BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Padding(PaddingMode::NONE))); - - int increment = 7; - string message(240, 'a'); - AuthorizationSet input_params = - AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE); - AuthorizationSet output_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, input_params, &output_params)); - - string ciphertext; - int32_t input_consumed; - for (size_t i = 0; i < message.size(); i += increment) - EXPECT_EQ(ErrorCode::OK, - Update(message.substr(i, increment), &ciphertext, &input_consumed)); - EXPECT_EQ(ErrorCode::OK, Finish(&ciphertext)); - EXPECT_EQ(message.size(), ciphertext.size()); - - // Move TAG_NONCE into input_params - input_params = output_params; - input_params.push_back(TAG_BLOCK_MODE, BlockMode::CBC); - input_params.push_back(TAG_PADDING, PaddingMode::NONE); - output_params.Clear(); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, input_params, &output_params)); - string plaintext; - for (size_t i = 0; i < ciphertext.size(); i += increment) - EXPECT_EQ(ErrorCode::OK, - Update(ciphertext.substr(i, increment), &plaintext, &input_consumed)); - EXPECT_EQ(ErrorCode::OK, Finish(&plaintext)); - EXPECT_EQ(ciphertext.size(), plaintext.size()); - EXPECT_EQ(message, plaintext); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(EncryptionOperationsTest); - -typedef KeyMintAidlTestBase MaxOperationsTest; - -/* - * MaxOperationsTest.TestLimitAes - * - * Verifies that the max uses per boot tag works correctly with AES keys. - */ -TEST_P(MaxOperationsTest, TestLimitAes) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .EcbMode() - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAX_USES_PER_BOOT, 3))); - - string message = "1234567890123456"; - - auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE); - - EncryptMessage(message, params); - EncryptMessage(message, params); - EncryptMessage(message, params); - - // Fourth time should fail. - EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::ENCRYPT, params)); -} - -/* - * MaxOperationsTest.TestLimitAes - * - * Verifies that the max uses per boot tag works correctly with RSA keys. - */ -TEST_P(MaxOperationsTest, TestLimitRsa) { - if (SecLevel() == SecurityLevel::STRONGBOX) return; - - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(1024, 65537) - .NoDigestOrPadding() - .Authorization(TAG_MAX_USES_PER_BOOT, 3))); - - string message = "1234567890123456"; - - auto params = AuthorizationSetBuilder().NoDigestOrPadding(); - - SignMessage(message, params); - SignMessage(message, params); - SignMessage(message, params); - - // Fourth time should fail. - EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::SIGN, params)); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(MaxOperationsTest); - -typedef KeyMintAidlTestBase AddEntropyTest; - -/* - * AddEntropyTest.AddEntropy - * - * Verifies that the addRngEntropy method doesn't blow up. There's no way to test that entropy - * is actually added. - */ -TEST_P(AddEntropyTest, AddEntropy) { - string data = "foo"; - EXPECT_TRUE(keyMint().addRngEntropy(vector<uint8_t>(data.begin(), data.end())).isOk()); -} - -/* - * AddEntropyTest.AddEmptyEntropy - * - * Verifies that the addRngEntropy method doesn't blow up when given an empty buffer. - */ -TEST_P(AddEntropyTest, AddEmptyEntropy) { - EXPECT_TRUE(keyMint().addRngEntropy(AidlBuf()).isOk()); -} - -/* - * AddEntropyTest.AddLargeEntropy - * - * Verifies that the addRngEntropy method doesn't blow up when given a largish amount of data. - */ -TEST_P(AddEntropyTest, AddLargeEntropy) { - EXPECT_TRUE(keyMint().addRngEntropy(AidlBuf(string(2 * 1024, 'a'))).isOk()); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(AddEntropyTest); - -typedef KeyMintAidlTestBase AttestationTest; - -/* - * AttestationTest.RsaAttestation - * - * Verifies that attesting to RSA keys works and generates the expected output. - */ -// TODO(seleneh) add attestation tests back after decided on the new attestation -// behavior under generateKey and importKey - -typedef KeyMintAidlTestBase KeyDeletionTest; - -/** - * KeyDeletionTest.DeleteKey - * - * This test checks that if rollback protection is implemented, DeleteKey invalidates a formerly - * valid key blob. - */ -TEST_P(KeyDeletionTest, DeleteKey) { - auto error = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_ROLLBACK_RESISTANCE)); - ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK); - - // Delete must work if rollback protection is implemented - if (error == ErrorCode::OK) { - AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced); - ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE)); - - ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */)); - - string message = "12345678901234567890123456789012"; - AuthorizationSet begin_out_params; - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, key_blob_, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE), - &begin_out_params)); - AbortIfNeeded(); - key_blob_ = AidlBuf(); - } -} - -/** - * KeyDeletionTest.DeleteInvalidKey - * - * This test checks that the HAL excepts invalid key blobs.. - */ -TEST_P(KeyDeletionTest, DeleteInvalidKey) { - // Generate key just to check if rollback protection is implemented - auto error = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_ROLLBACK_RESISTANCE)); - ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK); - - // Delete must work if rollback protection is implemented - if (error == ErrorCode::OK) { - AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced); - ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE)); - - // Delete the key we don't care about the result at this point. - DeleteKey(); - - // Now create an invalid key blob and delete it. - key_blob_ = AidlBuf("just some garbage data which is not a valid key blob"); - - ASSERT_EQ(ErrorCode::OK, DeleteKey()); - } -} - -/** - * KeyDeletionTest.DeleteAllKeys - * - * This test is disarmed by default. To arm it use --arm_deleteAllKeys. - * - * BEWARE: This test has serious side effects. All user keys will be lost! This includes - * FBE/FDE encryption keys, which means that the device will not even boot until after the - * device has been wiped manually (e.g., fastboot flashall -w), and new FBE/FDE keys have - * been provisioned. Use this test only on dedicated testing devices that have no valuable - * credentials stored in Keystore/Keymint. - */ -TEST_P(KeyDeletionTest, DeleteAllKeys) { - if (!arm_deleteAllKeys) return; - auto error = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED) - .Authorization(TAG_ROLLBACK_RESISTANCE)); - ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK); - - // Delete must work if rollback protection is implemented - if (error == ErrorCode::OK) { - AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced); - ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE)); - - ASSERT_EQ(ErrorCode::OK, DeleteAllKeys()); - - string message = "12345678901234567890123456789012"; - AuthorizationSet begin_out_params; - - EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, - Begin(KeyPurpose::SIGN, key_blob_, - AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE), - &begin_out_params)); - AbortIfNeeded(); - key_blob_ = AidlBuf(); - } -} - -INSTANTIATE_KEYMINT_AIDL_TEST(KeyDeletionTest); - -using UpgradeKeyTest = KeyMintAidlTestBase; - -/* - * UpgradeKeyTest.UpgradeKey - * - * Verifies that calling upgrade key on an up-to-date key works (i.e. does nothing). - */ -TEST_P(UpgradeKeyTest, UpgradeKey) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .AesEncryptionKey(128) - .Padding(PaddingMode::NONE) - .Authorization(TAG_NO_AUTH_REQUIRED))); - - auto result = UpgradeKey(key_blob_); - - // Key doesn't need upgrading. Should get okay, but no new key blob. - EXPECT_EQ(result, std::make_pair(ErrorCode::OK, vector<uint8_t>())); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(UpgradeKeyTest); - -using ClearOperationsTest = KeyMintAidlTestBase; - -/* - * ClearSlotsTest.TooManyOperations - * - * Verifies that TOO_MANY_OPERATIONS is returned after the max number of - * operations are started without being finished or aborted. Also verifies - * that aborting the operations clears the operations. - * - */ -TEST_P(ClearOperationsTest, TooManyOperations) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaEncryptionKey(2048, 65537) - .Padding(PaddingMode::NONE))); - - auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); - constexpr size_t max_operations = 100; // set to arbituary large number - sp<IKeyMintOperation> op_handles[max_operations]; - AuthorizationSet out_params; - ErrorCode result; - size_t i; - - for (i = 0; i < max_operations; i++) { - result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]); - if (ErrorCode::OK != result) { - break; - } - } - EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result); - // Try again just in case there's a weird overflow bug - EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, - Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params)); - for (size_t j = 0; j < i; j++) { - EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j])) - << "Aboort failed for i = " << j << std::endl; - } - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params)); - AbortIfNeeded(); -} - -INSTANTIATE_KEYMINT_AIDL_TEST(ClearOperationsTest); - -typedef KeyMintAidlTestBase TransportLimitTest; - -/* - * TransportLimitTest.FinishInput - * - * Verifies that passing input data to finish succeeds as expected. - */ -TEST_P(TransportLimitTest, LargeFinishInput) { - ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .AesEncryptionKey(128) - .BlockMode(BlockMode::ECB) - .Padding(PaddingMode::NONE))); - - for (int msg_size = 8 /* 256 bytes */; msg_size <= 11 /* 2 KiB */; msg_size++) { - auto cipher_params = - AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE); - - AuthorizationSet out_params; - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, cipher_params, &out_params)); - - string plain_message = std::string(1 << msg_size, 'x'); - string encrypted_message; - auto rc = Finish(plain_message, &encrypted_message); - - EXPECT_EQ(ErrorCode::OK, rc); - EXPECT_EQ(plain_message.size(), encrypted_message.size()) - << "Encrypt finish returned OK, but did not consume all of the given input"; - cipher_params.push_back(out_params); - - EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params)); - - string decrypted_message; - rc = Finish(encrypted_message, &decrypted_message); - EXPECT_EQ(ErrorCode::OK, rc); - EXPECT_EQ(plain_message.size(), decrypted_message.size()) - << "Decrypt finish returned OK, did not consume all of the given input"; - } -} - -INSTANTIATE_KEYMINT_AIDL_TEST(TransportLimitTest); - -} // namespace android::hardware::security::keymint::test - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - for (int i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - if (std::string(argv[i]) == "--arm_deleteAllKeys") { - arm_deleteAllKeys = true; - } - if (std::string(argv[i]) == "--dump_attestations") { - dump_Attestations = true; - } - } - } - return RUN_ALL_TESTS(); -} |