summaryrefslogtreecommitdiff
path: root/security/keymint/aidl/vts/functional/KeyMintTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintTest.cpp')
-rw-r--r--security/keymint/aidl/vts/functional/KeyMintTest.cpp4058
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();
-}