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