Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: webrtc/base/sslidentity_unittest.cc

Issue 1189583002: Support generation of EC keys using P256 curve and support ECDSA certs. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: address feedback from juberti Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 20 matching lines...) Expand all
31 "-----END CERTIFICATE-----\n"; 31 "-----END CERTIFICATE-----\n";
32 32
33 const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA, 33 const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA,
34 0xC3, 0x7E, 0x6D, 0x33, 34 0xC3, 0x7E, 0x6D, 0x33,
35 0xCF, 0xE2, 0x69, 0x9D, 35 0xCF, 0xE2, 0x69, 0x9D,
36 0x74, 0xE6, 0xF6, 0x8A, 36 0x74, 0xE6, 0xF6, 0x8A,
37 0x9E, 0x47, 0xA7, 0xCA}; 37 0x9E, 0x47, 0xA7, 0xCA};
38 38
39 class SSLIdentityTest : public testing::Test { 39 class SSLIdentityTest : public testing::Test {
40 public: 40 public:
41 SSLIdentityTest() : 41 SSLIdentityTest()
42 identity1_(), identity2_() { 42 : identity_rsa1_(),
juberti1 2015/07/21 22:54:13 These don't need to be initialized.
torbjorng (webrtc) 2015/08/17 12:12:45 Done.
43 } 43 identity_rsa2_(),
44 identity_ecdsa1_(),
45 identity_ecdsa2_() {}
44 46
45 ~SSLIdentityTest() { 47 ~SSLIdentityTest() {
46 } 48 }
47 49
48 virtual void SetUp() { 50 virtual void SetUp() {
49 identity1_.reset(SSLIdentity::Generate("test1")); 51 identity_rsa1_.reset(SSLIdentity::Generate("test1", rtc::KT_RSA));
50 identity2_.reset(SSLIdentity::Generate("test2")); 52 identity_rsa2_.reset(SSLIdentity::Generate("test2", rtc::KT_RSA));
53 identity_ecdsa1_.reset(SSLIdentity::Generate("test3", rtc::KT_ECDSA));
54 identity_ecdsa2_.reset(SSLIdentity::Generate("test4", rtc::KT_ECDSA));
51 55
52 ASSERT_TRUE(identity1_); 56 ASSERT_TRUE(identity_rsa1_);
53 ASSERT_TRUE(identity2_); 57 ASSERT_TRUE(identity_rsa2_);
58 ASSERT_TRUE(identity_ecdsa1_);
59 ASSERT_TRUE(identity_ecdsa2_);
54 60
55 test_cert_.reset( 61 test_cert_.reset(rtc::SSLCertificate::FromPEMString(kTestCertificate));
56 rtc::SSLCertificate::FromPEMString(kTestCertificate));
57 ASSERT_TRUE(test_cert_); 62 ASSERT_TRUE(test_cert_);
58 } 63 }
59 64
60 void TestGetSignatureDigestAlgorithm() { 65 void TestGetSignatureDigestAlgorithm() {
61 std::string digest_algorithm; 66 std::string digest_algorithm;
62 // Both NSSIdentity::Generate and OpenSSLIdentity::Generate are 67
63 // hard-coded to generate RSA-SHA256 certificates. 68 ASSERT_TRUE(identity_rsa1_->certificate().GetSignatureDigestAlgorithm(
64 ASSERT_TRUE(identity1_->certificate().GetSignatureDigestAlgorithm(
65 &digest_algorithm));
66 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
67 ASSERT_TRUE(identity2_->certificate().GetSignatureDigestAlgorithm(
68 &digest_algorithm)); 69 &digest_algorithm));
69 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm); 70 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
70 71
72 ASSERT_TRUE(identity_rsa2_->certificate().GetSignatureDigestAlgorithm(
73 &digest_algorithm));
74 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
75
76 ASSERT_TRUE(identity_ecdsa1_->certificate().GetSignatureDigestAlgorithm(
77 &digest_algorithm));
78 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
79
80 ASSERT_TRUE(identity_ecdsa2_->certificate().GetSignatureDigestAlgorithm(
81 &digest_algorithm));
82 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
83
71 // The test certificate has an MD5-based signature. 84 // The test certificate has an MD5-based signature.
72 ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm)); 85 ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm));
73 ASSERT_EQ(rtc::DIGEST_MD5, digest_algorithm); 86 ASSERT_EQ(rtc::DIGEST_MD5, digest_algorithm);
74 } 87 }
75 88
76 void TestDigest(const std::string &algorithm, size_t expected_len, 89 typedef unsigned char DigestType[64]; // 64 is the largest hash used here.
juberti1 2015/07/21 22:54:13 You can use MessageDigest::kMaxSize instead of 64
torbjorng (webrtc) 2015/08/17 12:12:45 Done.
77 const unsigned char *expected_digest = NULL) { 90
78 unsigned char digest1[64]; 91 void TestDigestHelper(DigestType digest,
79 unsigned char digest1b[64]; 92 const SSLIdentity* identity,
80 unsigned char digest2[64]; 93 const std::string& algorithm,
81 size_t digest1_len; 94 size_t expected_len) {
82 size_t digest1b_len; 95 DigestType digest1;
83 size_t digest2_len; 96 size_t digest_len;
84 bool rv; 97 bool rv;
85 98
86 rv = identity1_->certificate().ComputeDigest(algorithm, 99 memset(digest, 0, expected_len);
87 digest1, sizeof(digest1), 100 rv = identity->certificate().ComputeDigest(algorithm, digest,
88 &digest1_len); 101 sizeof(DigestType), &digest_len);
89 EXPECT_TRUE(rv); 102 EXPECT_TRUE(rv);
90 EXPECT_EQ(expected_len, digest1_len); 103 EXPECT_EQ(expected_len, digest_len);
91 104
92 rv = identity1_->certificate().ComputeDigest(algorithm, 105 // Repeat digest computation for the identity as a sanity check.
93 digest1b, sizeof(digest1b), 106 memset(digest1, 0xff, expected_len);
94 &digest1b_len); 107 rv = identity->certificate().ComputeDigest(algorithm, digest1,
108 sizeof(DigestType), &digest_len);
95 EXPECT_TRUE(rv); 109 EXPECT_TRUE(rv);
96 EXPECT_EQ(expected_len, digest1b_len); 110 EXPECT_EQ(expected_len, digest_len);
97 EXPECT_EQ(0, memcmp(digest1, digest1b, expected_len));
98 111
112 EXPECT_EQ(0, memcmp(digest, digest1, expected_len));
113 }
99 114
100 rv = identity2_->certificate().ComputeDigest(algorithm, 115 void TestDigest(const std::string& algorithm, size_t expected_len) {
juberti1 2015/07/21 22:54:13 I would call this TestDigestForGeneratedCerts, or
torbjorng (webrtc) 2015/08/17 12:12:45 Done.
101 digest2, sizeof(digest2), 116 DigestType digest[4];
102 &digest2_len);
103 EXPECT_TRUE(rv);
104 EXPECT_EQ(expected_len, digest2_len);
105 EXPECT_NE(0, memcmp(digest1, digest2, expected_len));
106 117
107 // If we have an expected hash for the test cert, check it. 118 ASSERT_TRUE(expected_len <= 64);
juberti1 2015/07/21 22:54:13 Suggest using <= sizeof(digest[0]), to avoid accid
torbjorng (webrtc) 2015/08/17 12:12:45 Done, except using sizeof(DigestType).
108 if (expected_digest) {
109 unsigned char digest3[64];
110 size_t digest3_len;
111 119
112 rv = test_cert_->ComputeDigest(algorithm, digest3, sizeof(digest3), 120 TestDigestHelper(digest[0], identity_rsa1_.get(), algorithm, expected_len);
113 &digest3_len); 121 TestDigestHelper(digest[1], identity_rsa2_.get(), algorithm, expected_len);
114 EXPECT_TRUE(rv); 122 TestDigestHelper(digest[2], identity_ecdsa1_.get(), algorithm,
115 EXPECT_EQ(expected_len, digest3_len); 123 expected_len);
116 EXPECT_EQ(0, memcmp(digest3, expected_digest, expected_len)); 124 TestDigestHelper(digest[3], identity_ecdsa2_.get(), algorithm,
125 expected_len);
126
127 // Sanity check that all four digests are unique. This could theoretically
128 // fail, since SHA256 collisions have a non-zero probability.
129 for (int i = 0; i < 4; i++) {
130 for (int j = 0; j < 4; j++) {
131 if (i != j)
132 EXPECT_NE(0, memcmp(digest[i], digest[j], expected_len));
133 }
117 } 134 }
118 } 135 }
119 136
137 void TestDigestExample(const std::string& algorithm,
juberti1 2015/07/21 22:54:13 I would call this TestDigestForFixedCert
torbjorng (webrtc) 2015/08/17 12:12:45 Done.
138 size_t expected_len,
139 const unsigned char* expected_digest) {
140 bool rv;
141 DigestType digest;
142 size_t digest_len;
143
144 ASSERT_TRUE(expected_len <= 64);
juberti1 2015/07/21 22:54:13 <= sizeof(digest)
torbjorng (webrtc) 2015/08/17 12:12:45 Done.
145
146 rv = test_cert_->ComputeDigest(algorithm, digest, sizeof(digest),
147 &digest_len);
148 EXPECT_TRUE(rv);
149 EXPECT_EQ(expected_len, digest_len);
150 EXPECT_EQ(0, memcmp(digest, expected_digest, expected_len));
151 }
152
120 private: 153 private:
121 rtc::scoped_ptr<SSLIdentity> identity1_; 154 rtc::scoped_ptr<SSLIdentity> identity_rsa1_;
122 rtc::scoped_ptr<SSLIdentity> identity2_; 155 rtc::scoped_ptr<SSLIdentity> identity_rsa2_;
156 rtc::scoped_ptr<SSLIdentity> identity_ecdsa1_;
157 rtc::scoped_ptr<SSLIdentity> identity_ecdsa2_;
123 rtc::scoped_ptr<rtc::SSLCertificate> test_cert_; 158 rtc::scoped_ptr<rtc::SSLCertificate> test_cert_;
124 }; 159 };
125 160
126 TEST_F(SSLIdentityTest, DigestSHA1) { 161 TEST_F(SSLIdentityTest, DigestSHA1) {
127 TestDigest(rtc::DIGEST_SHA_1, 20, kTestCertSha1); 162 TestDigestExample(rtc::DIGEST_SHA_1, 20, kTestCertSha1);
juberti1 2015/07/21 22:54:13 I would have a call to both TestDigestForGenerated
torbjorng (webrtc) 2015/08/17 12:12:45 Using more hashes checking fixed data makes sense.
128 } 163 }
129 164
130 // HASH_AlgSHA224 is not supported in the chromium linux build. 165 // HASH_AlgSHA224 is not supported in the chromium linux build.
131 #if SSL_USE_NSS 166 #if SSL_USE_NSS
132 TEST_F(SSLIdentityTest, DISABLED_DigestSHA224) { 167 TEST_F(SSLIdentityTest, DISABLED_DigestSHA224) {
133 #else 168 #else
134 TEST_F(SSLIdentityTest, DigestSHA224) { 169 TEST_F(SSLIdentityTest, DigestSHA224) {
135 #endif 170 #endif
136 TestDigest(rtc::DIGEST_SHA_224, 28); 171 TestDigest(rtc::DIGEST_SHA_224, 28);
137 } 172 }
138 173
139 TEST_F(SSLIdentityTest, DigestSHA256) { 174 TEST_F(SSLIdentityTest, DigestSHA256) {
140 TestDigest(rtc::DIGEST_SHA_256, 32); 175 TestDigest(rtc::DIGEST_SHA_256, 32);
141 } 176 }
142 177
143 TEST_F(SSLIdentityTest, DigestSHA384) { 178 TEST_F(SSLIdentityTest, DigestSHA384) {
144 TestDigest(rtc::DIGEST_SHA_384, 48); 179 TestDigest(rtc::DIGEST_SHA_384, 48);
145 } 180 }
146 181
147 TEST_F(SSLIdentityTest, DigestSHA512) { 182 TEST_F(SSLIdentityTest, DigestSHA512) {
148 TestDigest(rtc::DIGEST_SHA_512, 64); 183 TestDigest(rtc::DIGEST_SHA_512, 64);
149 } 184 }
150 185
151 TEST_F(SSLIdentityTest, FromPEMStrings) { 186 TEST_F(SSLIdentityTest, FromPEMStringsRSA) {
152 static const char kRSA_PRIVATE_KEY_PEM[] = 187 static const char kRSA_PRIVATE_KEY_PEM[] =
153 "-----BEGIN RSA PRIVATE KEY-----\n" 188 "-----BEGIN RSA PRIVATE KEY-----\n"
154 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" 189 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n"
155 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" 190 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n"
156 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" 191 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n"
157 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" 192 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n"
158 "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" 193 "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n"
159 "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" 194 "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n"
160 "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" 195 "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n"
161 "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" 196 "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n"
(...skipping 17 matching lines...) Expand all
179 "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" 214 "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n"
180 "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" 215 "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n"
181 "-----END CERTIFICATE-----\n"; 216 "-----END CERTIFICATE-----\n";
182 217
183 rtc::scoped_ptr<SSLIdentity> identity( 218 rtc::scoped_ptr<SSLIdentity> identity(
184 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kCERT_PEM)); 219 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kCERT_PEM));
185 EXPECT_TRUE(identity); 220 EXPECT_TRUE(identity);
186 EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString()); 221 EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString());
187 } 222 }
188 223
224 #if SSL_USE_OPENSSL
225 // This will not work on NSS as PK11_ImportDERPrivateKeyInfoAndReturnKey is not
226 // ready for EC keys. Furthermore, NSSIdentity::FromPEMStrings is currently
227 // hardwired for RSA (the header matching via kPemTypeRsaPrivateKey needs
228 // trivial generalization).
229 TEST_F(SSLIdentityTest, FromPEMStringsEC) {
230 static const char kRSA_PRIVATE_KEY_PEM[] =
231 "-----BEGIN EC PRIVATE KEY-----\n"
232 "MHcCAQEEIKkIztWLPbs4Y2zWv7VW2Ov4is2ifleCuPgRB8fRv3IkoAoGCCqGSM49\n"
233 "AwEHoUQDQgAEDPV33NrhSdhg9cBRkUWUXnVMXc3h17i9ARbSmNgminKcBXb8/y8L\n"
234 "A76cMWQPPM0ybHO8OS7ZVg2U/m+TwE1M2g==\n"
235 "-----END EC PRIVATE KEY-----\n";
236 static const char kCERT_PEM[] =
237 "-----BEGIN CERTIFICATE-----\n"
238 "MIIB0jCCAXmgAwIBAgIJAMCjpFt9t6LMMAoGCCqGSM49BAMCMEUxCzAJBgNVBAYT\n"
239 "AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn\n"
240 "aXRzIFB0eSBMdGQwIBcNMTUwNjMwMTMwMTIyWhgPMjI4OTA0MTMxMzAxMjJaMEUx\n"
241 "CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\n"
242 "cm5ldCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQM\n"
243 "9Xfc2uFJ2GD1wFGRRZRedUxdzeHXuL0BFtKY2CaKcpwFdvz/LwsDvpwxZA88zTJs\n"
244 "c7w5LtlWDZT+b5PATUzao1AwTjAdBgNVHQ4EFgQUYHq6nxNNIE832ZmaHc/noODO\n"
245 "rtAwHwYDVR0jBBgwFoAUYHq6nxNNIE832ZmaHc/noODOrtAwDAYDVR0TBAUwAwEB\n"
246 "/zAKBggqhkjOPQQDAgNHADBEAiAQRojsTyZG0BlKoU7gOt5h+yAMLl2cxmDtOIQr\n"
247 "GWP/PwIgJynB4AUDsPT0DWmethOXYijB5sY5UPd9DvgmiS/Mr6s=\n"
248 "-----END CERTIFICATE-----\n";
249
250 rtc::scoped_ptr<SSLIdentity> identity(
251 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kCERT_PEM));
252 EXPECT_TRUE(identity);
253 EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString());
254 }
255 #endif
256
189 TEST_F(SSLIdentityTest, PemDerConversion) { 257 TEST_F(SSLIdentityTest, PemDerConversion) {
190 std::string der; 258 std::string der;
191 EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der)); 259 EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der));
192 260
193 EXPECT_EQ(kTestCertificate, SSLIdentity::DerToPem( 261 EXPECT_EQ(kTestCertificate, SSLIdentity::DerToPem(
194 "CERTIFICATE", 262 "CERTIFICATE",
195 reinterpret_cast<const unsigned char*>(der.data()), der.length())); 263 reinterpret_cast<const unsigned char*>(der.data()), der.length()));
196 } 264 }
197 265
198 TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) { 266 TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) {
199 TestGetSignatureDigestAlgorithm(); 267 TestGetSignatureDigestAlgorithm();
200 } 268 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698