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