Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 <vector> | |
| 8 | |
| 9 #include "base/macros.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | |
| 11 | |
| 12 namespace gcm { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 // URL-safe base64 encoded (and plaintext representation of -) salt, key and dh. | |
| 17 // Included as preprocessor string literals for more convenient concatenation. | |
| 18 #define ENCODED_SALT "c2l4dGVlbmNvb2xieXRlcw" | |
| 19 #define ENCODED_KEY "c2V2ZW50ZWVuYnl0ZXN5YXk" | |
| 20 #define ENCODED_DH "bXlkaWZmaWVoZWxsbWFu" | |
| 21 | |
| 22 const char kDecodedSalt[] = "sixteencoolbytes"; | |
| 23 const char kDecodedKey[] = "seventeenbytesyay"; | |
| 24 const char kDecodedDh[] = "mydiffiehellman"; | |
| 25 | |
| 26 EncryptionHeaderValue CreateEncryptionHeaderValue( | |
| 27 const std::string& keyid, const std::string& salt, int64_t rs) { | |
| 28 EncryptionHeaderValue parsed; | |
| 29 parsed.keyid = keyid; | |
| 30 parsed.salt = salt; | |
| 31 parsed.rs = rs; | |
| 32 | |
| 33 return parsed; | |
| 34 } | |
| 35 | |
| 36 EncryptionKeyHeaderValue CreateEncryptionKeyHeaderValue( | |
| 37 const std::string& keyid, const std::string& key, const std::string& dh) { | |
| 38 EncryptionKeyHeaderValue header; | |
| 39 header.keyid = keyid; | |
| 40 header.key = key; | |
| 41 header.dh = dh; | |
| 42 | |
| 43 return header; | |
| 44 } | |
| 45 | |
| 46 TEST(EncryptionHeaderParsersTest, ParseSingleEncryptionHeaders) { | |
| 47 struct { | |
| 48 const char* const header; | |
| 49 EncryptionHeaderValue parsed; | |
| 50 } expected_results[] = { | |
| 51 { "keyid=foo; salt=" ENCODED_SALT "; rs=1024", | |
|
johnme
2015/07/20 19:15:19
Are you sure "; " is allowed? https://tools.ietf.o
Peter Beverloo
2015/07/20 22:44:33
The examples in the same draft use spaces, and thi
| |
| 52 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 53 { "keyid='foo'; salt='" ENCODED_SALT "'; rs='1024'", | |
|
johnme
2015/07/20 19:15:19
It seems according to https://tools.ietf.org/html/
Peter Beverloo
2015/07/20 22:44:33
Good point. Will do.
Peter Beverloo
2015/07/21 17:51:30
Done.
| |
| 54 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 55 { "keyid=\"foo\"; salt=\"" ENCODED_SALT "\"; rs=\"1024\"", | |
| 56 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 57 { "keyid=foo;salt=" ENCODED_SALT ";rs=1024", | |
| 58 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 59 { "keyid=foo;salt=" ENCODED_SALT ";rs=1024;random=yes", | |
| 60 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 61 { "rs=1024; salt=" ENCODED_SALT "; keyid=foo", | |
| 62 CreateEncryptionHeaderValue("foo", kDecodedSalt, 1024) }, | |
| 63 { "salt=" ENCODED_SALT "; keyid='foo; rs=1024'", | |
| 64 CreateEncryptionHeaderValue("foo; rs=1024", kDecodedSalt, 4096) }, | |
| 65 { "salt=" ENCODED_SALT "; rs=1024", | |
| 66 CreateEncryptionHeaderValue("", kDecodedSalt, 1024) }, | |
| 67 { "salt=" ENCODED_SALT, | |
| 68 CreateEncryptionHeaderValue("", kDecodedSalt, 4096) } | |
| 69 }; | |
| 70 | |
| 71 for (size_t i = 0; i < arraysize(expected_results); i++) { | |
| 72 SCOPED_TRACE(i); | |
|
johnme
2015/07/21 14:34:43
Nice :)
| |
| 73 | |
| 74 std::vector<EncryptionHeaderValue> result; | |
| 75 ASSERT_TRUE(ParseEncryptionHeader(expected_results[i].header, &result)); | |
| 76 ASSERT_EQ(1u, result.size()); | |
| 77 | |
| 78 EXPECT_EQ(expected_results[i].parsed.keyid, result[0].keyid); | |
| 79 EXPECT_EQ(expected_results[i].parsed.salt, result[0].salt); | |
| 80 EXPECT_EQ(expected_results[i].parsed.rs, result[0].rs); | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 TEST(EncryptionHeaderParsersTest, ParseInvalidSingleEncryptionHeaders) { | |
| 85 const char* const expected_failures[] = { | |
| 86 // The "salt" attribute is required. | |
| 87 "keyid=foo", | |
| 88 // The "salt" attribute must be exactly 16-bytes, base64 URL encoded. | |
| 89 "salt=foobar", | |
| 90 "salt='c2l4dGVlbmNvb2xieXRlcw=='", | |
| 91 // Non-decimal record sizes are not supported. | |
| 92 "salt=" ENCODED_SALT ";rs=bar", | |
| 93 // Record sizes smaller than 2 are not supported. | |
|
johnme
2015/07/21 14:34:43
Please also check that a record size of 9,223,372,
Peter Beverloo
2015/07/21 17:51:30
Done.
| |
| 94 "salt=" ENCODED_SALT ";rs=0" | |
| 95 }; | |
| 96 | |
| 97 for (size_t i = 0; i < arraysize(expected_failures); i++) { | |
| 98 SCOPED_TRACE(i); | |
| 99 | |
| 100 std::vector<EncryptionHeaderValue> result; | |
| 101 ASSERT_FALSE(ParseEncryptionHeader(expected_failures[i], &result)); | |
| 102 EXPECT_EQ(0u, result.size()); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 TEST(EncryptionHeaderParsersTest, ParseMultipleEncryptionHeaders) { | |
|
johnme
2015/07/20 19:15:19
Please add a test that you support the freaky empt
Peter Beverloo
2015/07/21 17:51:30
Added a comma.
| |
| 107 const char* const header = | |
| 108 "keyid=foo1; salt=" ENCODED_SALT "; rs=1024," | |
| 109 "keyid='foo2, '; salt=" ENCODED_SALT "; rs=2048"; | |
| 110 | |
| 111 std::vector<EncryptionHeaderValue> results; | |
| 112 ASSERT_TRUE(ParseEncryptionHeader(header, &results)); | |
| 113 ASSERT_EQ(2u, results.size()); | |
| 114 | |
| 115 EXPECT_EQ("foo1", results[0].keyid); | |
| 116 EXPECT_EQ(kDecodedSalt, results[0].salt); | |
| 117 EXPECT_EQ(1024, results[0].rs); | |
| 118 | |
| 119 EXPECT_EQ("foo2, ", results[1].keyid); | |
| 120 EXPECT_EQ(kDecodedSalt, results[1].salt); | |
| 121 EXPECT_EQ(2048, results[1].rs); | |
| 122 } | |
| 123 | |
| 124 TEST(EncryptionHeaderParsersTest, ParseSingleEncryptionKeyHeader) { | |
| 125 struct { | |
| 126 const char* const header; | |
| 127 EncryptionKeyHeaderValue parsed; | |
| 128 } expected_results[] = { | |
| 129 { "keyid=foo; key=" ENCODED_KEY "; dh=" ENCODED_DH, | |
|
johnme
2015/07/20 19:15:19
Similarly are you sure "; " is allowed?
Peter Beverloo
2015/07/20 22:44:33
See earlier comment.
| |
| 130 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 131 { "keyid='foo'; key='" ENCODED_KEY "'; dh='" ENCODED_DH "'", | |
| 132 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 133 { "keyid=\"foo\"; key=\"" ENCODED_KEY "\"; dh=\"" ENCODED_DH "\"", | |
| 134 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 135 { "keyid=foo;key=" ENCODED_KEY ";dh=" ENCODED_DH "", | |
| 136 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 137 { "keyid=foo;key=" ENCODED_KEY ";dh=" ENCODED_DH ";random=yes", | |
| 138 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 139 { "dh=" ENCODED_DH "; key=" ENCODED_KEY "; keyid=foo", | |
| 140 CreateEncryptionKeyHeaderValue("foo", kDecodedKey, kDecodedDh) }, | |
| 141 { "keyid=foo", | |
| 142 CreateEncryptionKeyHeaderValue("foo", "", "") }, | |
| 143 { "key=" ENCODED_KEY "", | |
| 144 CreateEncryptionKeyHeaderValue("", kDecodedKey, "") }, | |
| 145 { "dh=" ENCODED_DH "", | |
| 146 CreateEncryptionKeyHeaderValue("", "", kDecodedDh) } | |
| 147 }; | |
| 148 | |
| 149 for (size_t i = 0; i < arraysize(expected_results); i++) { | |
| 150 SCOPED_TRACE(i); | |
| 151 | |
| 152 std::vector<EncryptionKeyHeaderValue> result; | |
| 153 ASSERT_TRUE(ParseEncryptionKeyHeader(expected_results[i].header, &result)); | |
| 154 ASSERT_EQ(1u, result.size()); | |
| 155 | |
| 156 EXPECT_EQ(expected_results[i].parsed.keyid, result[0].keyid); | |
| 157 EXPECT_EQ(expected_results[i].parsed.key, result[0].key); | |
| 158 EXPECT_EQ(expected_results[i].parsed.dh, result[0].dh); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 TEST(EncryptionHeaderParsersTest, ParseInvalidSingleEncryptionKeyHeaders) { | |
| 163 const char* const expected_failures[] = { | |
| 164 // The "key" attribute must be at least 16-bytes, base64 URL encoded. | |
| 165 "key=foo/bar", | |
| 166 "key=c2hvcnRrZXk", | |
| 167 "key='c2l4dGVlbmNvb2xieXRlcw=='", | |
| 168 // The "dh" attribute must contain a base64 URL encoded-value. | |
| 169 "dh=foo/bar", | |
| 170 "dh='ZGg='" | |
| 171 }; | |
| 172 | |
| 173 for (size_t i = 0; i < arraysize(expected_failures); i++) { | |
| 174 SCOPED_TRACE(i); | |
| 175 | |
| 176 std::vector<EncryptionKeyHeaderValue> result; | |
| 177 ASSERT_FALSE(ParseEncryptionKeyHeader(expected_failures[i], &result)); | |
| 178 EXPECT_EQ(0u, result.size()); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 TEST(EncryptionHeaderParsersTest, ParseMultipleEncryptionKeyHeaders) { | |
| 183 const char* const header = | |
| 184 "keyid=foo1; key=" ENCODED_KEY "; dh=" ENCODED_DH "," | |
| 185 "keyid='foo2, '; key=c29tZW90aGVybG9uZ2tleQ; dh=ZGhmb29iYXI"; | |
| 186 | |
| 187 std::vector<EncryptionKeyHeaderValue> results; | |
| 188 ASSERT_TRUE(ParseEncryptionKeyHeader(header, &results)); | |
| 189 ASSERT_EQ(2u, results.size()); | |
| 190 | |
| 191 EXPECT_EQ("foo1", results[0].keyid); | |
| 192 EXPECT_EQ(kDecodedKey, results[0].key); | |
| 193 EXPECT_EQ(kDecodedDh, results[0].dh); | |
| 194 | |
| 195 EXPECT_EQ("foo2, ", results[1].keyid); | |
| 196 EXPECT_EQ("someotherlongkey", results[1].key); | |
| 197 EXPECT_EQ("dhfoobar", results[1].dh); | |
| 198 } | |
| 199 | |
| 200 } // namespace | |
| 201 | |
| 202 } // namespace gcm | |
| OLD | NEW |