xref: /aosp_15_r20/external/tink/cc/subtle/aes_gcm_siv_boringssl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 #include "tink/subtle/aes_gcm_siv_boringssl.h"
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/escaping.h"
27 #include "absl/strings/str_cat.h"
28 #include "tink/aead/internal/wycheproof_aead.h"
29 #include "tink/config/tink_fips.h"
30 #include "tink/internal/ssl_util.h"
31 #include "tink/subtle/subtle_util.h"
32 #include "tink/util/secret_data.h"
33 #include "tink/util/statusor.h"
34 #include "tink/util/test_matchers.h"
35 
36 namespace crypto {
37 namespace tink {
38 namespace subtle {
39 namespace {
40 
41 constexpr absl::string_view kKey256Hex =
42     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
43 constexpr absl::string_view kMessage = "Some data to encrypt.";
44 constexpr absl::string_view kAssociatedData = "Some data to authenticate.";
45 
46 constexpr int kIvSizeInBytes = 12;
47 constexpr int kTagSizeInBytes = 16;
48 
49 using ::crypto::tink::test::IsOk;
50 using ::crypto::tink::test::StatusIs;
51 using ::testing::AllOf;
52 using ::testing::Eq;
53 using ::testing::Not;
54 using ::testing::SizeIs;
55 using ::testing::TestWithParam;
56 using ::testing::ValuesIn;
57 
TEST(AesGcmSivBoringSslTest,EncryptDecrypt)58 TEST(AesGcmSivBoringSslTest, EncryptDecrypt) {
59   if (IsFipsModeEnabled()) {
60     GTEST_SKIP() << "Not supported in FIPS-only mode";
61   }
62 
63   util::SecretData key =
64       util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
65   if (!internal::IsBoringSsl()) {
66     EXPECT_THAT(AesGcmSivBoringSsl::New(key).status(),
67                 StatusIs(absl::StatusCode::kUnimplemented));
68   } else {
69     util::StatusOr<std::unique_ptr<Aead>> aead = AesGcmSivBoringSsl::New(key);
70     ASSERT_THAT(aead, IsOk());
71 
72     util::StatusOr<std::string> ciphertext =
73         (*aead)->Encrypt(kMessage, kAssociatedData);
74     ASSERT_THAT(ciphertext, IsOk());
75     EXPECT_THAT(*ciphertext,
76                 SizeIs(kMessage.size() + kIvSizeInBytes + kTagSizeInBytes));
77     util::StatusOr<std::string> plaintext =
78         (*aead)->Decrypt(*ciphertext, kAssociatedData);
79     ASSERT_THAT(plaintext, IsOk());
80     EXPECT_EQ(*plaintext, kMessage);
81   }
82 }
83 
TEST(AesGcmSivBoringSslTest,DecryptFailsIfCiphertextTooSmall)84 TEST(AesGcmSivBoringSslTest, DecryptFailsIfCiphertextTooSmall) {
85   if (!internal::IsBoringSsl()) {
86     GTEST_SKIP() << "Unimplemented with OpenSSL";
87   }
88   if (IsFipsModeEnabled()) {
89     GTEST_SKIP() << "Not supported in FIPS-only mode";
90   }
91 
92   util::SecretData key =
93       util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
94   util::StatusOr<std::unique_ptr<Aead>> aead = AesGcmSivBoringSsl::New(key);
95   ASSERT_THAT(aead, IsOk());
96 
97   for (int i = 1; i < kIvSizeInBytes + kTagSizeInBytes; i++) {
98     std::string ciphertext;
99     ResizeStringUninitialized(&ciphertext, i);
100     EXPECT_THAT((*aead)->Decrypt(ciphertext, kAssociatedData).status(),
101                 StatusIs(absl::StatusCode::kInvalidArgument));
102   }
103 }
104 
TEST(AesGcmSivBoringSslTest,TestFipsOnly)105 TEST(AesGcmSivBoringSslTest, TestFipsOnly) {
106   if (!internal::IsBoringSsl()) {
107     GTEST_SKIP() << "Unimplemented with OpenSSL";
108   }
109   if (!IsFipsModeEnabled()) {
110     GTEST_SKIP() << "Only supported in FIPS-only mode";
111   }
112 
113   util::SecretData key128 = util::SecretDataFromStringView(
114       absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f"));
115   util::SecretData key256 =
116       util::SecretDataFromStringView(absl::HexStringToBytes(
117           "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"));
118 
119   EXPECT_THAT(AesGcmSivBoringSsl::New(key128).status(),
120               StatusIs(absl::StatusCode::kInternal));
121   EXPECT_THAT(AesGcmSivBoringSsl::New(key256).status(),
122               StatusIs(absl::StatusCode::kInternal));
123 }
124 
125 class AesGcmSivBoringSslWycheproofTest
126     : public TestWithParam<internal::WycheproofTestVector> {
SetUp()127   void SetUp() override {
128     if (!internal::IsBoringSsl()) {
129       GTEST_SKIP() << "Unimplemented with OpenSSL";
130     }
131     if (IsFipsModeEnabled()) {
132       GTEST_SKIP() << "Not supported in FIPS-only mode";
133     }
134     internal::WycheproofTestVector test_vector = GetParam();
135     if ((test_vector.key.size() != 16 && test_vector.key.size() != 32) ||
136         test_vector.nonce.size() != kIvSizeInBytes ||
137         test_vector.tag.size() != kTagSizeInBytes) {
138       GTEST_SKIP() << "Unsupported parameters: key size "
139                    << test_vector.key.size()
140                    << " nonce size: " << test_vector.nonce.size()
141                    << " tag size: " << test_vector.tag.size();
142     }
143   }
144 };
145 
TEST_P(AesGcmSivBoringSslWycheproofTest,Decrypt)146 TEST_P(AesGcmSivBoringSslWycheproofTest, Decrypt) {
147   internal::WycheproofTestVector test_vector = GetParam();
148   util::SecretData key = util::SecretDataFromStringView(test_vector.key);
149   util::StatusOr<std::unique_ptr<Aead>> cipher = AesGcmSivBoringSsl::New(key);
150   ASSERT_THAT(cipher, IsOk());
151   std::string ciphertext =
152       absl::StrCat(test_vector.nonce, test_vector.ct, test_vector.tag);
153   util::StatusOr<std::string> plaintext =
154       (*cipher)->Decrypt(ciphertext, test_vector.aad);
155   if (plaintext.ok()) {
156     EXPECT_NE(test_vector.expected, "invalid");
157     EXPECT_EQ(*plaintext, test_vector.msg);
158   } else {
159     EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable"))))
160         << "Could not decrypt test with tcId: " << test_vector.id
161         << " iv_size: " << test_vector.nonce.size()
162         << " tag_size: " << test_vector.tag.size()
163         << " key_size: " << key.size() << "; error: " << plaintext.status();
164   }
165 }
166 
167 INSTANTIATE_TEST_SUITE_P(AesGcmSivBoringSslWycheproofTests,
168                          AesGcmSivBoringSslWycheproofTest,
169                          ValuesIn(internal::ReadWycheproofTestVectors(
170                              /*file_name=*/"aes_gcm_siv_test.json")));
171 
172 }  // namespace
173 }  // namespace subtle
174 }  // namespace tink
175 }  // namespace crypto
176