1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include "src/core/tsi/alts/frame_protector/alts_counter.h"
20
21 #include <gtest/gtest.h>
22
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
25
26 #include "src/core/lib/gprpp/crash.h"
27 #include "test/core/tsi/alts/crypt/gsec_test_util.h"
28
29 const size_t kSmallCounterSize = 4;
30 const size_t kSmallOverflowSize = 1;
31 const size_t kGcmCounterSize = 12;
32 const size_t kGcmOverflowSize = 5;
33
do_bytes_represent_client(alts_counter * ctr,unsigned char *,size_t size)34 static bool do_bytes_represent_client(alts_counter* ctr,
35 unsigned char* /*counter*/, size_t size) {
36 return (ctr->counter[size - 1] & 0x80) == 0x80;
37 }
38
alts_counter_test_input_sanity_check(size_t counter_size,size_t overflow_size)39 static void alts_counter_test_input_sanity_check(size_t counter_size,
40 size_t overflow_size) {
41 alts_counter* ctr = nullptr;
42 char* error_details = nullptr;
43
44 // Input sanity check on alts_counter_create().
45 // Invalid counter size.
46 grpc_status_code status =
47 alts_counter_create(true, 0, overflow_size, &ctr, &error_details);
48 ASSERT_TRUE(gsec_test_expect_compare_code_and_substr(
49 status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
50 "counter_size is invalid."));
51 gpr_free(error_details);
52
53 // Invalid overflow size.
54 status = alts_counter_create(true, counter_size, 0, &ctr, &error_details);
55 ASSERT_TRUE(gsec_test_expect_compare_code_and_substr(
56 status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
57 "overflow_size is invalid."));
58 gpr_free(error_details);
59
60 // alts_counter is nullptr.
61 status = alts_counter_create(true, counter_size, overflow_size, nullptr,
62 &error_details);
63 ASSERT_TRUE(gsec_test_expect_compare_code_and_substr(
64 status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
65 "crypter_counter is nullptr."));
66 gpr_free(error_details);
67
68 status = alts_counter_create(true, counter_size, overflow_size, &ctr,
69 &error_details);
70 ASSERT_EQ(status, GRPC_STATUS_OK);
71
72 // Input sanity check on alts_counter_increment().
73 // crypter_counter is nullptr.
74 bool is_overflow = false;
75 status = alts_counter_increment(nullptr, &is_overflow, &error_details);
76 ASSERT_TRUE(gsec_test_expect_compare_code_and_substr(
77 status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
78 "crypter_counter is nullptr."));
79 gpr_free(error_details);
80 // is_overflow is nullptr.
81 status = alts_counter_increment(ctr, nullptr, &error_details);
82 ASSERT_TRUE(gsec_test_expect_compare_code_and_substr(
83 status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
84 "is_overflow is nullptr."));
85 gpr_free(error_details);
86 alts_counter_destroy(ctr);
87 }
88
alts_counter_test_overflow_full_range(bool is_client,size_t counter_size,size_t overflow_size)89 static void alts_counter_test_overflow_full_range(bool is_client,
90 size_t counter_size,
91 size_t overflow_size) {
92 alts_counter* ctr = nullptr;
93 char* error_details = nullptr;
94 grpc_status_code status = alts_counter_create(
95 is_client, counter_size, overflow_size, &ctr, &error_details);
96 ASSERT_EQ(status, GRPC_STATUS_OK);
97 unsigned char* expected =
98 static_cast<unsigned char*>(gpr_zalloc(counter_size));
99 if (is_client) {
100 expected[counter_size - 1] = 0x80;
101 }
102 // Do a single iteration to ensure the counter is initialized as expected.
103 ASSERT_EQ(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
104 counter_size),
105 is_client);
106 ASSERT_EQ(memcmp(alts_counter_get_counter(ctr), expected, counter_size), 0);
107 bool is_overflow = false;
108 ASSERT_EQ(alts_counter_increment(ctr, &is_overflow, &error_details),
109 GRPC_STATUS_OK);
110 ASSERT_FALSE(is_overflow);
111 ///
112 /// The counter can return 2^{overflow_size * 8} counters. The
113 /// high-order bit is fixed to the client/server. The last call will yield a
114 /// useable counter, but overflow the counter object.
115 ///
116 int iterations = 1 << (overflow_size * 8);
117 int ind = 1;
118 for (ind = 1; ind < iterations - 1; ind++) {
119 ASSERT_EQ(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
120 counter_size),
121 is_client);
122 ASSERT_EQ(alts_counter_increment(ctr, &is_overflow, &error_details),
123 GRPC_STATUS_OK);
124 ASSERT_FALSE(is_overflow);
125 }
126 ASSERT_EQ(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
127 counter_size),
128 is_client);
129 ASSERT_EQ(alts_counter_increment(ctr, &is_overflow, &error_details),
130 GRPC_STATUS_FAILED_PRECONDITION);
131 ASSERT_TRUE(is_overflow);
132 gpr_free(expected);
133 alts_counter_destroy(ctr);
134 }
135
136 // Set the counter manually and make sure it overflows as expected.
alts_counter_test_overflow_single_increment(bool is_client,size_t counter_size,size_t overflow_size)137 static void alts_counter_test_overflow_single_increment(bool is_client,
138 size_t counter_size,
139 size_t overflow_size) {
140 alts_counter* ctr = nullptr;
141 char* error_details = nullptr;
142 grpc_status_code status = alts_counter_create(
143 is_client, counter_size, overflow_size, &ctr, &error_details);
144 ASSERT_EQ(status, GRPC_STATUS_OK);
145 unsigned char* expected =
146 static_cast<unsigned char*>(gpr_zalloc(counter_size));
147 memset(expected, 0xFF, overflow_size);
148 expected[0] = 0xFE;
149
150 if (is_client) {
151 expected[counter_size - 1] = 0x80;
152 }
153 memcpy(ctr->counter, expected, counter_size);
154 ASSERT_EQ(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
155 counter_size),
156 is_client);
157 ASSERT_EQ(memcmp(expected, alts_counter_get_counter(ctr), counter_size), 0);
158 bool is_overflow = false;
159 ASSERT_EQ(alts_counter_increment(ctr, &is_overflow, &error_details),
160 GRPC_STATUS_OK);
161 ASSERT_FALSE(is_overflow);
162 ASSERT_EQ(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
163 counter_size),
164 is_client);
165 expected[0] = static_cast<unsigned char>(expected[0] + 1);
166 ASSERT_EQ(memcmp(expected, alts_counter_get_counter(ctr), counter_size), 0);
167 ASSERT_EQ(alts_counter_increment(ctr, &is_overflow, &error_details),
168 GRPC_STATUS_FAILED_PRECONDITION);
169 ASSERT_TRUE(is_overflow);
170 gpr_free(expected);
171 alts_counter_destroy(ctr);
172 }
173
TEST(AltsCounterTest,MainTest)174 TEST(AltsCounterTest, MainTest) {
175 alts_counter_test_input_sanity_check(kGcmCounterSize, kGcmOverflowSize);
176 alts_counter_test_overflow_full_range(true, kSmallCounterSize,
177 kSmallOverflowSize);
178 alts_counter_test_overflow_full_range(false, kSmallCounterSize,
179 kSmallOverflowSize);
180 alts_counter_test_overflow_single_increment(true, kGcmCounterSize,
181 kGcmOverflowSize);
182 alts_counter_test_overflow_single_increment(false, kGcmCounterSize,
183 kGcmOverflowSize);
184 }
185
main(int argc,char ** argv)186 int main(int argc, char** argv) {
187 ::testing::InitGoogleTest(&argc, argv);
188 return RUN_ALL_TESTS();
189 }
190