xref: /aosp_15_r20/external/tink/cc/subtle/aes_gcm_hkdf_stream_segment_encrypter_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 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_hkdf_stream_segment_encrypter.h"
18 
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/str_cat.h"
27 #include "tink/subtle/random.h"
28 #include "tink/util/status.h"
29 #include "tink/util/statusor.h"
30 #include "tink/util/test_util.h"
31 
32 
33 namespace crypto {
34 namespace tink {
35 namespace subtle {
36 namespace {
37 
38 using ::testing::HasSubstr;
39 
TEST(AesGcmHkdfStreamSegmentEncrypterTest,testBasic)40 TEST(AesGcmHkdfStreamSegmentEncrypterTest, testBasic) {
41   for (int key_size : {16, 32}) {
42     for (int ciphertext_offset : {0, 5, 10}) {
43       for (int ct_segment_size : {80, 128, 200}) {
44         SCOPED_TRACE(absl::StrCat(
45             "key_size = ", key_size,
46             ", ciphertext_offset = ", ciphertext_offset,
47             ", ciphertext_segment_size = ", ct_segment_size));
48 
49         // Construct an encrypter.
50         AesGcmHkdfStreamSegmentEncrypter::Params params;
51         params.key = Random::GetRandomKeyBytes(key_size);
52         params.salt = Random::GetRandomBytes(key_size);
53         params.ciphertext_offset = ciphertext_offset;
54         params.ciphertext_segment_size = ct_segment_size;
55         auto result = AesGcmHkdfStreamSegmentEncrypter::New(params);
56         EXPECT_TRUE(result.ok()) << result.status();
57 
58         // Use the Constructed encrypter.
59         auto enc = std::move(result.value());
60         EXPECT_EQ(0, enc->get_segment_number());
61         int header_size = key_size + /* nonce_prefix_size = */ 7 + 1;
62         EXPECT_EQ(header_size, enc->get_header().size());
63         EXPECT_EQ(header_size, enc->get_header()[0]);
64         EXPECT_EQ(params.salt, std::string(reinterpret_cast<const char*>(
65                                                enc->get_header().data() + 1),
66                                            key_size));
67         EXPECT_EQ(ct_segment_size, enc->get_ciphertext_segment_size());
68         EXPECT_EQ(ct_segment_size - /* tag_size = */ 16,
69                   enc->get_plaintext_segment_size());
70         EXPECT_EQ(ciphertext_offset, enc->get_ciphertext_offset());
71         int segment_number = 0;
72         for (int pt_size : {1, 10, enc->get_plaintext_segment_size()}) {
73           for (bool is_last_segment : {false, true}) {
74             SCOPED_TRACE(absl::StrCat(
75                 "plaintext_size = ", pt_size,
76                 ", is_last_segment = ", is_last_segment));
77             std::vector<uint8_t> pt(pt_size, 'p');
78             std::vector<uint8_t> ct;
79             auto status = enc->EncryptSegment(pt, is_last_segment, &ct);
80             EXPECT_TRUE(status.ok()) << status;
81             EXPECT_EQ(pt_size + /* tag_size = */ 16, ct.size());
82             segment_number++;
83             EXPECT_EQ(segment_number, enc->get_segment_number());
84           }
85         }
86 
87         // Try encryption with wrong params.
88         std::vector<uint8_t> pt(enc->get_plaintext_segment_size() + 1, 'p');
89         auto status = enc->EncryptSegment(pt, true, nullptr);
90         EXPECT_FALSE(status.ok());
91         EXPECT_THAT(std::string(status.message()),
92                     HasSubstr("plaintext too long"));
93         pt.resize(enc->get_plaintext_segment_size());
94         status = enc->EncryptSegment(pt, true, nullptr);
95         EXPECT_FALSE(status.ok());
96         EXPECT_THAT(std::string(status.message()),
97                     HasSubstr("must be non-null"));
98       }
99     }
100   }
101 }
102 
TEST(AesGcmHkdfStreamSegmentEncrypterTest,testWrongKeySize)103 TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongKeySize) {
104   for (int key_size : {12, 24, 64}) {
105     for (int ciphertext_offset : {0, 5, 10}) {
106       for (int ct_segment_size : {128, 200}) {
107            SCOPED_TRACE(absl::StrCat(
108                "key_size = ", key_size,
109                ", ciphertext_offset = ", ciphertext_offset,
110                ", ciphertext_segment_size = ", ct_segment_size));
111         AesGcmHkdfStreamSegmentEncrypter::Params params;
112         params.key = Random::GetRandomKeyBytes(key_size);
113         params.salt = Random::GetRandomBytes(key_size);
114         params.ciphertext_offset = ciphertext_offset;
115         params.ciphertext_segment_size = ct_segment_size;
116         auto result = AesGcmHkdfStreamSegmentEncrypter::New(params);
117         EXPECT_FALSE(result.ok());
118         EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
119         EXPECT_THAT(std::string(result.status().message()),
120                     HasSubstr("must have 16 or 32 bytes"));
121       }
122     }
123   }
124 }
125 
TEST(AesGcmHkdfStreamSegmentEncrypterTest,testWrongSaltSize)126 TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongSaltSize) {
127   for (int key_size : {16, 32}) {
128     for (int salt_size_delta : {-3, -1, 1, 5, 16}) {
129       SCOPED_TRACE(absl::StrCat(
130           "key_size = ", key_size,
131           ", salt_size = ", key_size + salt_size_delta));
132       AesGcmHkdfStreamSegmentEncrypter::Params params;
133       params.key = Random::GetRandomKeyBytes(key_size);
134       params.salt = Random::GetRandomBytes(key_size + salt_size_delta);
135       params.ciphertext_offset = 0;
136       params.ciphertext_segment_size = 128;
137       auto result = AesGcmHkdfStreamSegmentEncrypter::New(params);
138       EXPECT_FALSE(result.ok());
139       EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
140       EXPECT_THAT(std::string(result.status().message()),
141                   HasSubstr("same size as the key"));
142     }
143   }
144 }
145 
TEST(AesGcmHkdfStreamSegmentEncrypterTest,testWrongCiphertextOffset)146 TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongCiphertextOffset) {
147   for (int key_size : {16, 32}) {
148     for (int ciphertext_offset : {-16, -10, -3, -1}) {
149       SCOPED_TRACE(absl::StrCat(
150           "key_size = ", key_size,
151           ", ciphertext_offset = ", ciphertext_offset));
152       AesGcmHkdfStreamSegmentEncrypter::Params params;
153       params.key = Random::GetRandomKeyBytes(key_size);
154       params.salt = Random::GetRandomBytes(key_size);
155       params.ciphertext_offset = ciphertext_offset;
156       params.ciphertext_segment_size = 128;
157       auto result = AesGcmHkdfStreamSegmentEncrypter::New(params);
158       EXPECT_FALSE(result.ok());
159       EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
160       EXPECT_THAT(std::string(result.status().message()),
161                   HasSubstr("must be non-negative"));
162     }
163   }
164 }
165 
TEST(AesGcmHkdfStreamSegmentEncrypterTest,testWrongCiphertextSegmentSize)166 TEST(AesGcmHkdfStreamSegmentEncrypterTest, testWrongCiphertextSegmentSize) {
167   for (int key_size : {16, 32}) {
168     for (int ciphertext_offset : {0, 1, 5, 10}) {
169       int min_ct_segment_size = key_size + ciphertext_offset +
170                                 8 +   // nonce_prefix_size + 1
171                                 16 +   // tag_size
172                                 1;
173       for (int ct_segment_size : {min_ct_segment_size - 5,
174               min_ct_segment_size - 1, min_ct_segment_size,
175               min_ct_segment_size + 1, min_ct_segment_size + 10}) {
176         SCOPED_TRACE(absl::StrCat(
177             "key_size = ", key_size,
178             ", ciphertext_offset = ", ciphertext_offset,
179             ", ciphertext_segment_size = ", ct_segment_size));
180         AesGcmHkdfStreamSegmentEncrypter::Params params;
181         params.key = Random::GetRandomKeyBytes(key_size);
182         params.salt = Random::GetRandomBytes(key_size);
183         params.ciphertext_offset = ciphertext_offset;
184         params.ciphertext_segment_size = ct_segment_size;
185         auto result = AesGcmHkdfStreamSegmentEncrypter::New(params);
186         if (ct_segment_size < min_ct_segment_size) {
187           EXPECT_FALSE(result.ok());
188           EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
189           EXPECT_THAT(std::string(result.status().message()),
190                       HasSubstr("too small"));
191         } else {
192           EXPECT_TRUE(result.ok()) << result.status();
193         }
194       }
195     }
196   }
197 }
198 
199 }  // namespace
200 }  // namespace subtle
201 }  // namespace tink
202 }  // namespace crypto
203