| // 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. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| #include "tink/aead/kms_envelope_aead.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "absl/memory/memory.h" |
| #include "absl/strings/str_cat.h" |
| #include "tink/registry.h" |
| #include "tink/aead/aead_config.h" |
| #include "tink/aead/aead_key_templates.h" |
| #include "tink/mac/mac_key_templates.h" |
| #include "tink/util/status.h" |
| #include "tink/util/statusor.h" |
| #include "tink/util/test_util.h" |
| #include "tink/util/test_matchers.h" |
| #include "gtest/gtest.h" |
| |
| |
| namespace crypto { |
| namespace tink { |
| namespace { |
| |
| using crypto::tink::test::IsOk; |
| using crypto::tink::test::StatusIs; |
| using crypto::tink::test::DummyAead; |
| using testing::HasSubstr; |
| |
| TEST(KmsEnvelopeAeadTest, BasicEncryptDecrypt) { |
| EXPECT_THAT(AeadConfig::Register(), IsOk()); |
| |
| auto dek_template = AeadKeyTemplates::Aes128Eax(); |
| std::string remote_aead_name = "kms-backed-aead"; |
| auto remote_aead = absl::make_unique<DummyAead>(remote_aead_name); |
| |
| auto aead_result = KmsEnvelopeAead::New(dek_template, std::move(remote_aead)); |
| EXPECT_THAT(aead_result.status(), IsOk()); |
| auto aead = std::move(aead_result.ValueOrDie()); |
| std::string message = "Some data to encrypt."; |
| std::string aad = "Some data to authenticate."; |
| auto encrypt_result = aead->Encrypt(message, aad); |
| EXPECT_THAT(encrypt_result.status(), IsOk()); |
| auto decrypt_result = aead->Decrypt(encrypt_result.ValueOrDie(), aad); |
| EXPECT_THAT(decrypt_result.status(), IsOk()); |
| EXPECT_EQ(decrypt_result.ValueOrDie(), message); |
| } |
| |
| TEST(KmsEnvelopeAeadTest, NullAead) { |
| auto dek_template = AeadKeyTemplates::Aes128Eax(); |
| auto aead_result = KmsEnvelopeAead::New(dek_template, nullptr); |
| EXPECT_THAT(aead_result.status(), StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("non-null"))); |
| } |
| |
| TEST(KmsEnvelopeAeadTest, MissingDekKeyManager) { |
| Registry::Reset(); |
| auto dek_template = AeadKeyTemplates::Aes128Eax(); |
| std::string remote_aead_name = "kms-backed-aead"; |
| auto remote_aead = absl::make_unique<DummyAead>(remote_aead_name); |
| auto aead_result = KmsEnvelopeAead::New(dek_template, std::move(remote_aead)); |
| EXPECT_THAT(aead_result.status(), StatusIs(util::error::NOT_FOUND, |
| HasSubstr("AesEaxKey"))); |
| } |
| |
| TEST(KmsEnvelopeAeadTest, WrongDekPrimitive) { |
| EXPECT_THAT(AeadConfig::Register(), IsOk()); |
| auto dek_template = MacKeyTemplates::HmacSha256(); |
| std::string remote_aead_name = "kms-backed-aead"; |
| auto remote_aead = absl::make_unique<DummyAead>(remote_aead_name); |
| auto aead_result = KmsEnvelopeAead::New(dek_template, std::move(remote_aead)); |
| EXPECT_THAT(aead_result.status(), |
| StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("not among supported primitives"))); |
| } |
| |
| TEST(KmsEnvelopeAeadTest, DecryptionErrors) { |
| EXPECT_THAT(AeadConfig::Register(), IsOk()); |
| |
| auto dek_template = AeadKeyTemplates::Aes128Gcm(); |
| std::string remote_aead_name = "kms-backed-aead"; |
| auto remote_aead = absl::make_unique<DummyAead>(remote_aead_name); |
| |
| auto aead_result = KmsEnvelopeAead::New(dek_template, std::move(remote_aead)); |
| EXPECT_THAT(aead_result.status(), IsOk()); |
| auto aead = std::move(aead_result.ValueOrDie()); |
| std::string message = "Some data to encrypt."; |
| std::string aad = "Some data to authenticate."; |
| auto encrypt_result = aead->Encrypt(message, aad); |
| EXPECT_THAT(encrypt_result.status(), IsOk()); |
| auto ct = encrypt_result.ValueOrDie(); |
| |
| // Empty ciphertext. |
| auto decrypt_result = aead->Decrypt("", aad); |
| EXPECT_THAT(decrypt_result.status(), StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("too short"))); |
| |
| // Short ciphertext. |
| decrypt_result = aead->Decrypt("sh", aad); |
| EXPECT_THAT(decrypt_result.status(), StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("too short"))); |
| |
| // Truncated ciphertext. |
| decrypt_result = aead->Decrypt(ct.substr(2), aad); |
| EXPECT_THAT(decrypt_result.status(), StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("invalid"))); |
| |
| // Corrupted ciphertext. |
| auto ct_copy = ct; |
| ct_copy[4] = 'a'; // corrupt serialized DEK. |
| decrypt_result = aead->Decrypt(ct_copy, aad); |
| EXPECT_THAT(decrypt_result.status(), StatusIs(util::error::INVALID_ARGUMENT, |
| HasSubstr("invalid"))); |
| |
| // Wrong associated data. |
| decrypt_result = aead->Decrypt(ct, "wrong aad"); |
| EXPECT_THAT(decrypt_result.status(), |
| StatusIs(util::error::INTERNAL, |
| HasSubstr("Authentication failed"))); |
| } |
| |
| |
| } // namespace |
| } // namespace tink |
| } // namespace crypto |