1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/gcm_driver/crypto/encryption_header_parsers.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <vector>
11
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace gcm {
17
18 namespace {
19
20 const uint64_t kDefaultRecordSize = 4096;
21
TEST(EncryptionHeaderParsersTest,ParseValidEncryptionHeaders)22 TEST(EncryptionHeaderParsersTest, ParseValidEncryptionHeaders) {
23 struct {
24 const char* const header;
25 const char* const parsed_keyid;
26 const char* const parsed_salt;
27 uint64_t parsed_rs;
28 } expected_results[] = {
29 { "keyid=foo;salt=c2l4dGVlbmNvb2xieXRlcw;rs=1024",
30 "foo", "sixteencoolbytes", 1024 },
31 { "keyid=foo; salt=c2l4dGVlbmNvb2xieXRlcw; rs=1024",
32 "foo", "sixteencoolbytes", 1024 },
33 { "KEYID=foo;SALT=c2l4dGVlbmNvb2xieXRlcw;RS=1024",
34 "foo", "sixteencoolbytes", 1024 },
35 { " keyid = foo ; salt = c2l4dGVlbmNvb2xieXRlcw ; rs = 1024 ",
36 "foo", "sixteencoolbytes", 1024 },
37 { "keyid=foo", "foo", "", kDefaultRecordSize },
38 { "keyid=foo;", "foo", "", kDefaultRecordSize },
39 { "keyid=\"foo\"", "foo", "", kDefaultRecordSize },
40 { "salt=c2l4dGVlbmNvb2xieXRlcw",
41 "", "sixteencoolbytes", kDefaultRecordSize },
42 { "rs=2048", "", "", 2048 },
43 { "keyid=foo;someothervalue=1;rs=42", "foo", "", 42 },
44 };
45
46 for (size_t i = 0; i < base::size(expected_results); i++) {
47 SCOPED_TRACE(i);
48
49 std::string header(expected_results[i].header);
50
51 EncryptionHeaderIterator iterator(header.begin(), header.end());
52 ASSERT_TRUE(iterator.GetNext());
53
54 EXPECT_EQ(expected_results[i].parsed_keyid, iterator.keyid());
55 EXPECT_EQ(expected_results[i].parsed_salt, iterator.salt());
56 EXPECT_EQ(expected_results[i].parsed_rs, iterator.rs());
57
58 EXPECT_FALSE(iterator.GetNext());
59 }
60 }
61
TEST(EncryptionHeaderParsersTest,ParseValidMultiValueEncryptionHeaders)62 TEST(EncryptionHeaderParsersTest, ParseValidMultiValueEncryptionHeaders) {
63 const size_t kNumberOfValues = 2u;
64
65 struct {
66 const char* const header;
67 struct {
68 const char* const keyid;
69 const char* const salt;
70 uint64_t rs;
71 } parsed_values[kNumberOfValues];
72 } expected_results[] = {
73 { "keyid=foo;salt=c2l4dGVlbmNvb2xieXRlcw;rs=1024,keyid=foo;salt=c2l4dGVlbm"
74 "Nvb2xieXRlcw;rs=1024",
75 { { "foo", "sixteencoolbytes", 1024 },
76 { "foo", "sixteencoolbytes", 1024 } } },
77 { "keyid=foo,salt=c2l4dGVlbmNvb2xieXRlcw;rs=1024",
78 { { "foo", "", kDefaultRecordSize },
79 { "", "sixteencoolbytes", 1024 } } },
80 { "keyid=foo,keyid=bar;salt=c2l4dGVlbmNvb2xieXRlcw;rs=1024",
81 { { "foo", "", kDefaultRecordSize },
82 { "bar", "sixteencoolbytes", 1024 } } },
83 { "keyid=\"foo,keyid=bar\",salt=c2l4dGVlbmNvb2xieXRlcw",
84 { { "foo,keyid=bar", "", kDefaultRecordSize },
85 { "", "sixteencoolbytes", kDefaultRecordSize } } },
86 };
87
88 for (size_t i = 0; i < base::size(expected_results); i++) {
89 SCOPED_TRACE(i);
90
91 std::string header(expected_results[i].header);
92
93 EncryptionHeaderIterator iterator(header.begin(), header.end());
94 for (size_t j = 0; j < kNumberOfValues; ++j) {
95 ASSERT_TRUE(iterator.GetNext());
96
97 EXPECT_EQ(expected_results[i].parsed_values[j].keyid, iterator.keyid());
98 EXPECT_EQ(expected_results[i].parsed_values[j].salt, iterator.salt());
99 EXPECT_EQ(expected_results[i].parsed_values[j].rs, iterator.rs());
100 }
101
102 EXPECT_FALSE(iterator.GetNext());
103 }
104 }
105
TEST(EncryptionHeaderParsersTest,ParseInvalidEncryptionHeaders)106 TEST(EncryptionHeaderParsersTest, ParseInvalidEncryptionHeaders) {
107 const char* const expected_failures[] = {
108 // Values in the name-value pairs are not optional.
109 "keyid",
110 "keyid=",
111 "keyid=foo;keyid",
112 "salt",
113 "salt=",
114 "rs",
115 "rs=",
116
117 // Supplying the same name multiple times in the same value is invalid.
118 "keyid=foo;keyid=bar",
119 "keyid=foo;bar=baz;keyid=qux",
120
121 // The salt must be a URL-safe base64 decodable string.
122 "salt=YmV/2ZXJ-sMDA",
123 "salt=dHdlbHZlY29vbGJ5dGVz=====",
124 "salt=c2l4dGVlbmNvb2xieXRlcw;salt=123$xyz",
125 "salt=123$xyz",
126
127 // The record size must be a positive decimal integer greater than one that
128 // does not start with a plus.
129 "rs=0",
130 "rs=0x13",
131 "rs=1",
132 "rs=-1",
133 "rs=+5",
134 "rs=99999999999999999999999999999999",
135 "rs=foobar",
136 };
137
138 const char* const expected_failures_second_iter[] = {
139 // Valid first field, missing value in the second field.
140 "keyid=foo,novaluekey",
141
142 // Valid first field, undecodable salt in the second field.
143 "salt=c2l4dGVlbmNvb2xieXRlcw,salt=123$xyz",
144
145 // Valid first field, invalid record size in the second field.
146 "rs=2,rs=0",
147 };
148
149 for (size_t i = 0; i < base::size(expected_failures); i++) {
150 SCOPED_TRACE(i);
151
152 std::string header(expected_failures[i]);
153
154 EncryptionHeaderIterator iterator(header.begin(), header.end());
155 EXPECT_FALSE(iterator.GetNext());
156 }
157
158 for (size_t i = 0; i < base::size(expected_failures_second_iter); i++) {
159 SCOPED_TRACE(i);
160
161 std::string header(expected_failures_second_iter[i]);
162
163 EncryptionHeaderIterator iterator(header.begin(), header.end());
164 EXPECT_TRUE(iterator.GetNext());
165 EXPECT_FALSE(iterator.GetNext());
166 }
167 }
168
TEST(EncryptionHeaderParsersTest,ParseValidCryptoKeyHeaders)169 TEST(EncryptionHeaderParsersTest, ParseValidCryptoKeyHeaders) {
170 struct {
171 const char* const header;
172 const char* const parsed_keyid;
173 const char* const parsed_aesgcm128;
174 const char* const parsed_dh;
175 } expected_results[] = {
176 { "keyid=foo;aesgcm128=c2l4dGVlbmNvb2xieXRlcw;dh=dHdlbHZlY29vbGJ5dGVz",
177 "foo", "sixteencoolbytes", "twelvecoolbytes" },
178 { "keyid=foo; aesgcm128=c2l4dGVlbmNvb2xieXRlcw; dh=dHdlbHZlY29vbGJ5dGVz",
179 "foo", "sixteencoolbytes", "twelvecoolbytes" },
180 { "keyid = foo ; aesgcm128 = c2l4dGVlbmNvb2xieXRlcw ; dh = dHdlbHZlY29vbGJ5"
181 "dGVz ",
182 "foo", "sixteencoolbytes", "twelvecoolbytes" },
183 { "KEYID=foo;AESGCM128=c2l4dGVlbmNvb2xieXRlcw;DH=dHdlbHZlY29vbGJ5dGVz",
184 "foo", "sixteencoolbytes", "twelvecoolbytes" },
185 { "keyid=foo", "foo", "", "" },
186 { "aesgcm128=c2l4dGVlbmNvb2xieXRlcw", "", "sixteencoolbytes", "" },
187 { "aesgcm128=\"c2l4dGVlbmNvb2xieXRlcw\"", "", "sixteencoolbytes", "" },
188 { "dh=dHdlbHZlY29vbGJ5dGVz", "", "", "twelvecoolbytes" },
189 { "keyid=foo;someothervalue=bar;aesgcm128=dHdlbHZlY29vbGJ5dGVz",
190 "foo", "twelvecoolbytes", "" },
191 };
192
193 for (size_t i = 0; i < base::size(expected_results); i++) {
194 SCOPED_TRACE(i);
195
196 std::string header(expected_results[i].header);
197
198 CryptoKeyHeaderIterator iterator(header.begin(), header.end());
199 ASSERT_TRUE(iterator.GetNext());
200
201 EXPECT_EQ(expected_results[i].parsed_keyid, iterator.keyid());
202 EXPECT_EQ(expected_results[i].parsed_aesgcm128, iterator.aesgcm128());
203 EXPECT_EQ(expected_results[i].parsed_dh, iterator.dh());
204
205 EXPECT_FALSE(iterator.GetNext());
206 }
207 }
208
TEST(EncryptionHeaderParsersTest,ParseValidMultiValueCryptoKeyHeaders)209 TEST(EncryptionHeaderParsersTest, ParseValidMultiValueCryptoKeyHeaders) {
210 const size_t kNumberOfValues = 2u;
211
212 struct {
213 const char* const header;
214 struct {
215 const char* const keyid;
216 const char* const aesgcm128;
217 const char* const dh;
218 } parsed_values[kNumberOfValues];
219 } expected_results[] = {
220 { "keyid=foo;aesgcm128=c2l4dGVlbmNvb2xieXRlcw;dh=dHdlbHZlY29vbGJ5dGVz,"
221 "keyid=bar;aesgcm128=dHdlbHZlY29vbGJ5dGVz;dh=c2l4dGVlbmNvb2xieXRlcw",
222 { { "foo", "sixteencoolbytes", "twelvecoolbytes" },
223 { "bar", "twelvecoolbytes", "sixteencoolbytes" } } },
224 { "keyid=foo,aesgcm128=c2l4dGVlbmNvb2xieXRlcw",
225 { { "foo", "", "" },
226 { "", "sixteencoolbytes", "" } } },
227 { "keyid=foo,keyid=bar;dh=dHdlbHZlY29vbGJ5dGVz",
228 { { "foo", "", "" },
229 { "bar", "", "twelvecoolbytes" } } },
230 { "keyid=\"foo,keyid=bar\",aesgcm128=c2l4dGVlbmNvb2xieXRlcw",
231 { { "foo,keyid=bar", "", "" },
232 { "", "sixteencoolbytes", "" } } },
233 };
234
235 for (size_t i = 0; i < base::size(expected_results); i++) {
236 SCOPED_TRACE(i);
237
238 std::string header(expected_results[i].header);
239
240 CryptoKeyHeaderIterator iterator(header.begin(), header.end());
241 for (size_t j = 0; j < kNumberOfValues; ++j) {
242 ASSERT_TRUE(iterator.GetNext());
243
244 EXPECT_EQ(expected_results[i].parsed_values[j].keyid, iterator.keyid());
245 EXPECT_EQ(expected_results[i].parsed_values[j].aesgcm128,
246 iterator.aesgcm128());
247 EXPECT_EQ(expected_results[i].parsed_values[j].dh, iterator.dh());
248 }
249
250 EXPECT_FALSE(iterator.GetNext());
251 }
252 }
253
TEST(EncryptionHeaderParsersTest,DISABLED_ParseInvalidCryptoKeyHeaders)254 TEST(EncryptionHeaderParsersTest, DISABLED_ParseInvalidCryptoKeyHeaders) {
255 const char* const expected_failures[] = {
256 // Values in the name-value pairs are not optional.
257 "keyid",
258 "keyid=",
259 "keyid=foo;keyid",
260 "aesgcm128",
261 "aesgcm128=",
262 "dh",
263 "dh=",
264
265 // Supplying the same name multiple times in the same value is invalid.
266 "keyid=foo;keyid=bar",
267 "keyid=foo;bar=baz;keyid=qux",
268
269 // The "aesgcm128" parameter must be a URL-safe base64 decodable string.
270 "aesgcm128=123$xyz",
271 "aesgcm128=foobar;aesgcm128=123$xyz",
272
273 // The "dh" parameter must be a URL-safe base64 decodable string.
274 "dh=YmV/2ZXJ-sMDA",
275 "dh=dHdlbHZlY29vbGJ5dGVz=====",
276 "dh=123$xyz",
277 };
278
279 const char* const expected_failures_second_iter[] = {
280 // Valid first field, missing value in the second field.
281 "keyid=foo,novaluekey",
282
283 // Valid first field, undecodable aesgcm128 value in the second field.
284 "dh=dHdlbHZlY29vbGJ5dGVz,aesgcm128=123$xyz",
285 };
286
287 for (size_t i = 0; i < base::size(expected_failures); i++) {
288 SCOPED_TRACE(i);
289
290 std::string header(expected_failures[i]);
291
292 CryptoKeyHeaderIterator iterator(header.begin(), header.end());
293 EXPECT_FALSE(iterator.GetNext());
294 }
295
296 for (size_t i = 0; i < base::size(expected_failures_second_iter); i++) {
297 SCOPED_TRACE(i);
298
299 std::string header(expected_failures_second_iter[i]);
300
301 CryptoKeyHeaderIterator iterator(header.begin(), header.end());
302 EXPECT_TRUE(iterator.GetNext());
303 EXPECT_FALSE(iterator.GetNext());
304 }
305 }
306
TEST(EncryptionHeaderParsersTest,SixValueHeader)307 TEST(EncryptionHeaderParsersTest, SixValueHeader) {
308 const std::string header("keyid=0,keyid=1,keyid=2,keyid=3,keyid=4,keyid=5");
309
310 EncryptionHeaderIterator encryption_iterator(header.begin(), header.end());
311 CryptoKeyHeaderIterator crypto_key_iterator(header.begin(), header.end());
312
313 for (size_t i = 0; i < 6; ++i) {
314 SCOPED_TRACE(i);
315
316 ASSERT_TRUE(encryption_iterator.GetNext());
317 ASSERT_TRUE(crypto_key_iterator.GetNext());
318 }
319
320 EXPECT_FALSE(encryption_iterator.GetNext());
321 EXPECT_FALSE(crypto_key_iterator.GetNext());
322 }
323
TEST(EncryptionHeaderParsersTest,InvalidHeadersResetOutput)324 TEST(EncryptionHeaderParsersTest, InvalidHeadersResetOutput) {
325 // Valid first field, invalid record size parameter in the second field.
326 const std::string encryption_header(
327 "keyid=foo;salt=c2l4dGVlbmNvb2xieXRlcw;rs=1024,rs=foobar");
328
329 // Valid first field, undecodable aesgcm128 parameter in the second field.
330 const std::string crypto_key_header(
331 "keyid=foo;aesgcm128=c2l4dGVlbmNvb2xieXRlcw;dh=dHdlbHZlY29vbGJ5dGVz,"
332 "aesgcm128=$$$");
333
334 EncryptionHeaderIterator encryption_iterator(
335 encryption_header.begin(), encryption_header.end());
336
337 ASSERT_EQ(0u, encryption_iterator.keyid().size());
338 ASSERT_EQ(0u, encryption_iterator.salt().size());
339 ASSERT_EQ(4096u, encryption_iterator.rs());
340
341 ASSERT_TRUE(encryption_iterator.GetNext());
342
343 EXPECT_EQ("foo", encryption_iterator.keyid());
344 EXPECT_EQ("sixteencoolbytes", encryption_iterator.salt());
345 EXPECT_EQ(1024u, encryption_iterator.rs());
346
347 ASSERT_FALSE(encryption_iterator.GetNext());
348
349 EXPECT_EQ(0u, encryption_iterator.keyid().size());
350 EXPECT_EQ(0u, encryption_iterator.salt().size());
351 EXPECT_EQ(4096u, encryption_iterator.rs());
352
353 CryptoKeyHeaderIterator crypto_key_iterator(
354 crypto_key_header.begin(), crypto_key_header.end());
355
356 ASSERT_EQ(0u, crypto_key_iterator.keyid().size());
357 ASSERT_EQ(0u, crypto_key_iterator.aesgcm128().size());
358 ASSERT_EQ(0u, crypto_key_iterator.dh().size());
359
360 ASSERT_TRUE(crypto_key_iterator.GetNext());
361
362 EXPECT_EQ("foo", crypto_key_iterator.keyid());
363 EXPECT_EQ("sixteencoolbytes", crypto_key_iterator.aesgcm128());
364 EXPECT_EQ("twelvecoolbytes", crypto_key_iterator.dh());
365
366 ASSERT_FALSE(crypto_key_iterator.GetNext());
367
368 EXPECT_EQ(0u, crypto_key_iterator.keyid().size());
369 EXPECT_EQ(0u, crypto_key_iterator.aesgcm128().size());
370 EXPECT_EQ(0u, crypto_key_iterator.dh().size());
371 }
372
373 } // namespace
374
375 } // namespace gcm
376