blob: 8e4d02db415217d4c964eb94d039452e57205133 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Yves Gerey3e707812018-11-28 15:47:4911#include <string.h>
jbauch555604a2016-04-26 10:13:2212#include <memory>
henrike@webrtc.orgf0488722014-05-13 18:00:2613#include <string>
Yves Gerey3e707812018-11-28 15:47:4914#include <vector>
henrike@webrtc.orgf0488722014-05-13 18:00:2615
Steve Anton1c9c9fc2019-02-14 23:13:0916#include "absl/strings/str_replace.h"
Yves Gerey3e707812018-11-28 15:47:4917#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0018#include "rtc_base/fake_ssl_identity.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "rtc_base/helpers.h"
Yves Gerey3e707812018-11-28 15:47:4920#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 17:11:0021#include "rtc_base/message_digest.h"
22#include "rtc_base/ssl_fingerprint.h"
23#include "rtc_base/ssl_identity.h"
Yves Gerey3e707812018-11-28 15:47:4924#include "test/gtest.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2625
26using rtc::SSLIdentity;
27
Yves Gerey665174f2018-06-19 13:03:0528const char kTestCertificate[] =
29 "-----BEGIN CERTIFICATE-----\n"
henrike@webrtc.orgf0488722014-05-13 18:00:2630 "MIIB6TCCAVICAQYwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV\n"
31 "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD\n"
32 "VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDAxMDE2MjIzMTAzWhcNMDMwMTE0\n"
33 "MjIzMTAzWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG\n"
34 "A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNl\n"
35 "cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIP\n"
36 "Fe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2//\n"
37 "Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCT0grFQeZaqYb5EYfk20XixZV4\n"
38 "GmyAbXMftG1Eo7qGiMhYzRwGNWxEYojf5PZkYZXvSqZ/ZXHXa4g59jK/rJNnaVGM\n"
39 "k+xIX8mxQvlV0n5O9PIha5BX5teZnkHKgL8aKKLKW1BK7YTngsfSzzaeame5iKfz\n"
40 "itAE+OjGF+PFKbwX8Q==\n"
41 "-----END CERTIFICATE-----\n";
42
Yves Gerey665174f2018-06-19 13:03:0543const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA, 0xC3, 0x7E, 0x6D,
44 0x33, 0xCF, 0xE2, 0x69, 0x9D, 0x74, 0xE6,
45 0xF6, 0x8A, 0x9E, 0x47, 0xA7, 0xCA};
Torbjorn Granlundb6d4ec42015-08-17 12:08:5946const unsigned char kTestCertSha224[] = {
Yves Gerey665174f2018-06-19 13:03:0547 0xd4, 0xce, 0xc6, 0xcf, 0x28, 0xcb, 0xe9, 0x77, 0x38, 0x36,
48 0xcf, 0xb1, 0x3b, 0x4a, 0xd7, 0xbd, 0xae, 0x24, 0x21, 0x08,
49 0xcf, 0x6a, 0x44, 0x0d, 0x3f, 0x94, 0x2a, 0x5b};
Torbjorn Granlundb6d4ec42015-08-17 12:08:5950const unsigned char kTestCertSha256[] = {
Yves Gerey665174f2018-06-19 13:03:0551 0x41, 0x6b, 0xb4, 0x93, 0x47, 0x79, 0x77, 0x24, 0x77, 0x0b, 0x8b,
52 0x2e, 0xa6, 0x2b, 0xe0, 0xf9, 0x0a, 0xed, 0x1f, 0x31, 0xa6, 0xf7,
53 0x5c, 0xa1, 0x5a, 0xc4, 0xb0, 0xa2, 0xa4, 0x78, 0xb9, 0x76};
Torbjorn Granlundb6d4ec42015-08-17 12:08:5954const unsigned char kTestCertSha384[] = {
Yves Gerey665174f2018-06-19 13:03:0555 0x42, 0x31, 0x9a, 0x79, 0x1d, 0xd6, 0x08, 0xbf, 0x3b, 0xba, 0x36, 0xd8,
56 0x37, 0x4a, 0x9a, 0x75, 0xd3, 0x25, 0x6e, 0x28, 0x92, 0xbe, 0x06, 0xb7,
57 0xc5, 0xa0, 0x83, 0xe3, 0x86, 0xb1, 0x03, 0xfc, 0x64, 0x47, 0xd6, 0xd8,
58 0xaa, 0xd9, 0x36, 0x60, 0x04, 0xcc, 0xbe, 0x7d, 0x6a, 0xe8, 0x34, 0x49};
Torbjorn Granlundb6d4ec42015-08-17 12:08:5959const unsigned char kTestCertSha512[] = {
Yves Gerey665174f2018-06-19 13:03:0560 0x51, 0x1d, 0xec, 0x02, 0x3d, 0x51, 0x45, 0xd3, 0xd8, 0x1d, 0xa4,
61 0x9d, 0x43, 0xc9, 0xee, 0x32, 0x6f, 0x4f, 0x37, 0xee, 0xab, 0x3f,
62 0x25, 0xdf, 0x72, 0xfc, 0x61, 0x1a, 0xd5, 0x92, 0xff, 0x6b, 0x28,
63 0x71, 0x58, 0xb3, 0xe1, 0x8a, 0x18, 0xcf, 0x61, 0x33, 0x0e, 0x14,
64 0xc3, 0x04, 0xaa, 0x07, 0xf6, 0xa5, 0xda, 0xdc, 0x42, 0x42, 0x22,
65 0x35, 0xce, 0x26, 0x58, 0x4a, 0x33, 0x6d, 0xbc, 0xb6};
henrike@webrtc.orgf0488722014-05-13 18:00:2666
hbose29352b2016-08-25 10:52:3867// These PEM strings were created by generating an identity with
68// |SSLIdentity::Generate| and invoking |identity->PrivateKeyToPEMString()|,
69// |identity->PublicKeyToPEMString()| and
70// |identity->certificate().ToPEMString()|. If the crypto library is updated,
71// and the update changes the string form of the keys, these will have to be
72// updated too. The fingerprint, fingerprint algorithm and base64 certificate
73// were created by calling |identity->certificate().GetStats()|.
74static const char kRSA_PRIVATE_KEY_PEM[] =
75 "-----BEGIN PRIVATE KEY-----\n"
76 "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMQPqDStRlYeDpkX\n"
77 "erRmv+a1naM8vSVSY0gG2plnrnofViWRW3MRqWC+020MsIj3hPZeSAnt/y/FL/nr\n"
78 "4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHwcFcMr31HLFvHr0ZgcFwbgIuFLNEl\n"
79 "7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAECgYA8FWBC5GcNtSBcIinkZyigF0A7\n"
80 "6j081sa+J/uNz4xUuI257ZXM6biygUhhvuXK06/XoIULJfhyN0fAm1yb0HtNhiUs\n"
81 "kMOYeon6b8FqFaPjrQf7Gr9FMiIHXNK19uegTMKztXyPZoUWlX84X0iawY95x0Y3\n"
82 "73f6P2rN2UOjlVVjAQJBAOKy3l2w3Zj2w0oAJox0eMwl+RxBNt1C42SHrob2mFUT\n"
83 "rytpVVYOasr8CoDI0kjacjI94sLum+buJoXXX6YTGO0CQQDdZwlYIEkoS3ftfxPa\n"
84 "Ai0YTBzAWvHJg0r8Gk/TkHo6IM+LSsZ9ZYUv/vBe4BKLw1I4hZ+bQvBiq+f8ROtk\n"
85 "+TDRAkAPL3ghwoU1h+IRBO2QHwUwd6K2N9AbBi4BP+168O3HVSg4ujeTKigRLMzv\n"
86 "T4R2iNt5bhfQgvdCgtVlxcWMdF8JAkBwDCg3eEdt5BuyjwBt8XH+/O4ED0KUWCTH\n"
87 "x00k5dZlupsuhE5Fwe4QpzXg3gekwdnHjyCCQ/NCDHvgOMTkmhQxAkA9V03KRX9b\n"
88 "bhvEzY/fu8gEp+EzsER96/D79az5z1BaMGL5OPM2xHBPJATKlswnAa7Lp3QKGZGk\n"
89 "TxslfL18J71s\n"
90 "-----END PRIVATE KEY-----\n";
91static const char kRSA_PUBLIC_KEY_PEM[] =
92 "-----BEGIN PUBLIC KEY-----\n"
93 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDED6g0rUZWHg6ZF3q0Zr/mtZ2j\n"
94 "PL0lUmNIBtqZZ656H1YlkVtzEalgvtNtDLCI94T2XkgJ7f8vxS/56+BGuzV3MHUa\n"
95 "Nf9cRCu1P3/3I0oNWrp8rxwh8HBXDK99Ryxbx69GYHBcG4CLhSzRJe5CuRzDvQD8\n"
96 "9Z7VI3pPAZgY/MjJfQIDAQAB\n"
97 "-----END PUBLIC KEY-----\n";
98static const char kRSA_CERT_PEM[] =
99 "-----BEGIN CERTIFICATE-----\n"
100 "MIIBnDCCAQWgAwIBAgIJAOEHLgeWYwrpMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNV\n"
101 "BAMMBXRlc3QxMB4XDTE2MDQyNDE4MTAyMloXDTE2MDUyNTE4MTAyMlowEDEOMAwG\n"
102 "A1UEAwwFdGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQPqDStRlYe\n"
103 "DpkXerRmv+a1naM8vSVSY0gG2plnrnofViWRW3MRqWC+020MsIj3hPZeSAnt/y/F\n"
104 "L/nr4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHwcFcMr31HLFvHr0ZgcFwbgIuF\n"
105 "LNEl7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAEwDQYJKoZIhvcNAQELBQADgYEA\n"
106 "C3ehaZFl+oEYN069C2ht/gMzuC77L854RF/x7xRtNZzkcg9TVgXXdM3auUvJi8dx\n"
107 "yTpU3ixErjQvoZew5ngXTEvTY8BSQUijJEaLWh8n6NDKRbEGTdAk8nPAmq9hdCFq\n"
108 "e3UkexqNHm3g/VxG4NUC1Y+w29ai0/Rgh+VvgbDwK+Q=\n"
109 "-----END CERTIFICATE-----\n";
110static const char kRSA_FINGERPRINT[] =
111 "3C:E8:B2:70:09:CF:A9:09:5A:F4:EF:8F:8D:8A:32:FF:EA:04:91:BA:6E:D4:17:78:16"
112 ":2A:EE:F9:9A:DD:E2:2B";
Yves Gerey665174f2018-06-19 13:03:05113static const char kRSA_FINGERPRINT_ALGORITHM[] = "sha-256";
hbose29352b2016-08-25 10:52:38114static const char kRSA_BASE64_CERTIFICATE[] =
115 "MIIBnDCCAQWgAwIBAgIJAOEHLgeWYwrpMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNVBAMMBXRlc3"
116 "QxMB4XDTE2MDQyNDE4MTAyMloXDTE2MDUyNTE4MTAyMlowEDEOMAwGA1UEAwwFdGVzdDEwgZ8w"
117 "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQPqDStRlYeDpkXerRmv+a1naM8vSVSY0gG2plnrn"
118 "ofViWRW3MRqWC+020MsIj3hPZeSAnt/y/FL/nr4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHw"
119 "cFcMr31HLFvHr0ZgcFwbgIuFLNEl7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAEwDQYJKoZIhv"
120 "cNAQELBQADgYEAC3ehaZFl+oEYN069C2ht/gMzuC77L854RF/x7xRtNZzkcg9TVgXXdM3auUvJ"
121 "i8dxyTpU3ixErjQvoZew5ngXTEvTY8BSQUijJEaLWh8n6NDKRbEGTdAk8nPAmq9hdCFqe3Ukex"
122 "qNHm3g/VxG4NUC1Y+w29ai0/Rgh+VvgbDwK+Q=";
123
124static const char kECDSA_PRIVATE_KEY_PEM[] =
125 "-----BEGIN PRIVATE KEY-----\n"
126 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/AkEA2hklq7dQ2rN\n"
127 "ZxYL6hOUACL4pn7P4FYlA3ZQhIChRANCAAR7YgdO3utP/8IqVRq8G4VZKreMAxeN\n"
128 "rUa12twthv4uFjuHAHa9D9oyAjncmn+xvZZRyVmKrA56jRzENcEEHoAg\n"
129 "-----END PRIVATE KEY-----\n";
130static const char kECDSA_PUBLIC_KEY_PEM[] =
131 "-----BEGIN PUBLIC KEY-----\n"
132 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEe2IHTt7rT//CKlUavBuFWSq3jAMX\n"
133 "ja1GtdrcLYb+LhY7hwB2vQ/aMgI53Jp/sb2WUclZiqwOeo0cxDXBBB6AIA==\n"
134 "-----END PUBLIC KEY-----\n";
135static const char kECDSA_CERT_PEM[] =
136 "-----BEGIN CERTIFICATE-----\n"
137 "MIIBFDCBu6ADAgECAgkArpkxjw62sW4wCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
138 "dGVzdDMwHhcNMTYwNDI0MTgxNDM4WhcNMTYwNTI1MTgxNDM4WjAQMQ4wDAYDVQQD\n"
139 "DAV0ZXN0MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHtiB07e60//wipVGrwb\n"
140 "hVkqt4wDF42tRrXa3C2G/i4WO4cAdr0P2jICOdyaf7G9llHJWYqsDnqNHMQ1wQQe\n"
141 "gCAwCgYIKoZIzj0EAwIDSAAwRQIhANyreQ/K5yuPPpirsd0e/4WGLHou6bIOSQks\n"
142 "DYzo56NmAiAKOr3u8ol3LmygbUCwEvtWrS8QcJDygxHPACo99hkekw==\n"
143 "-----END CERTIFICATE-----\n";
144static const char kECDSA_FINGERPRINT[] =
145 "9F:47:FA:88:76:3D:18:B8:00:A0:59:9D:C3:5D:34:0B:1F:B8:99:9E:68:DA:F3:A5:DA"
146 ":50:33:A9:FF:4D:31:89";
Yves Gerey665174f2018-06-19 13:03:05147static const char kECDSA_FINGERPRINT_ALGORITHM[] = "sha-256";
hbose29352b2016-08-25 10:52:38148static const char kECDSA_BASE64_CERTIFICATE[] =
149 "MIIBFDCBu6ADAgECAgkArpkxjw62sW4wCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwFdGVzdDMwHh"
150 "cNMTYwNDI0MTgxNDM4WhcNMTYwNTI1MTgxNDM4WjAQMQ4wDAYDVQQDDAV0ZXN0MzBZMBMGByqG"
151 "SM49AgEGCCqGSM49AwEHA0IABHtiB07e60//wipVGrwbhVkqt4wDF42tRrXa3C2G/i4WO4cAdr"
152 "0P2jICOdyaf7G9llHJWYqsDnqNHMQ1wQQegCAwCgYIKoZIzj0EAwIDSAAwRQIhANyreQ/K5yuP"
153 "Ppirsd0e/4WGLHou6bIOSQksDYzo56NmAiAKOr3u8ol3LmygbUCwEvtWrS8QcJDygxHPACo99h"
154 "kekw==";
155
156struct IdentityAndInfo {
157 std::unique_ptr<rtc::SSLIdentity> identity;
158 std::vector<std::string> ders;
159 std::vector<std::string> pems;
160 std::vector<std::string> fingerprints;
161};
162
163IdentityAndInfo CreateFakeIdentityAndInfoFromDers(
164 const std::vector<std::string>& ders) {
165 RTC_CHECK(!ders.empty());
166 IdentityAndInfo info;
167 info.ders = ders;
168 for (const std::string& der : ders) {
169 info.pems.push_back(rtc::SSLIdentity::DerToPem(
Yves Gerey665174f2018-06-19 13:03:05170 "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
hbose29352b2016-08-25 10:52:38171 der.length()));
172 }
Taylor Brandstetterc3928662018-02-23 21:04:51173 info.identity.reset(new rtc::FakeSSLIdentity(info.pems));
hbose29352b2016-08-25 10:52:38174 // Strip header/footer and newline characters of PEM strings.
175 for (size_t i = 0; i < info.pems.size(); ++i) {
Steve Anton1c9c9fc2019-02-14 23:13:09176 absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
177 {"-----END CERTIFICATE-----", ""},
178 {"\n", ""}},
179 &info.pems[i]);
hbose29352b2016-08-25 10:52:38180 }
Taylor Brandstetterc3928662018-02-23 21:04:51181 // Fingerprints for the whole certificate chain, starting with leaf
182 // certificate.
183 const rtc::SSLCertChain& chain = info.identity->cert_chain();
184 std::unique_ptr<rtc::SSLFingerprint> fp;
185 for (size_t i = 0; i < chain.GetSize(); i++) {
Steve Anton4905edb2018-10-16 02:27:44186 fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
Taylor Brandstetterc3928662018-02-23 21:04:51187 EXPECT_TRUE(fp);
188 info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
hbose29352b2016-08-25 10:52:38189 }
190 EXPECT_EQ(info.ders.size(), info.fingerprints.size());
191 return info;
192}
193
Mirko Bonadei6a489f22019-04-09 13:11:12194class SSLIdentityTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:26195 public:
Steve Anton9de3aac2017-10-24 17:08:26196 void SetUp() override {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59197 identity_rsa1_.reset(SSLIdentity::Generate("test1", rtc::KT_RSA));
198 identity_rsa2_.reset(SSLIdentity::Generate("test2", rtc::KT_RSA));
199 identity_ecdsa1_.reset(SSLIdentity::Generate("test3", rtc::KT_ECDSA));
200 identity_ecdsa2_.reset(SSLIdentity::Generate("test4", rtc::KT_ECDSA));
henrike@webrtc.orgf0488722014-05-13 18:00:26201
Torbjorn Granlundb6d4ec42015-08-17 12:08:59202 ASSERT_TRUE(identity_rsa1_);
203 ASSERT_TRUE(identity_rsa2_);
204 ASSERT_TRUE(identity_ecdsa1_);
205 ASSERT_TRUE(identity_ecdsa2_);
henrike@webrtc.orgf0488722014-05-13 18:00:26206
Steve Antonf25303e2018-10-16 22:23:31207 test_cert_ = rtc::SSLCertificate::FromPEMString(kTestCertificate);
henrike@webrtc.orgf0488722014-05-13 18:00:26208 ASSERT_TRUE(test_cert_);
209 }
210
211 void TestGetSignatureDigestAlgorithm() {
212 std::string digest_algorithm;
Torbjorn Granlundb6d4ec42015-08-17 12:08:59213
214 ASSERT_TRUE(identity_rsa1_->certificate().GetSignatureDigestAlgorithm(
henrike@webrtc.orgf0488722014-05-13 18:00:26215 &digest_algorithm));
Joachim Bauch1b794d52015-05-12 01:32:11216 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
Torbjorn Granlundb6d4ec42015-08-17 12:08:59217
218 ASSERT_TRUE(identity_rsa2_->certificate().GetSignatureDigestAlgorithm(
219 &digest_algorithm));
220 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
221
222 ASSERT_TRUE(identity_ecdsa1_->certificate().GetSignatureDigestAlgorithm(
223 &digest_algorithm));
224 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
225
226 ASSERT_TRUE(identity_ecdsa2_->certificate().GetSignatureDigestAlgorithm(
henrike@webrtc.orgf0488722014-05-13 18:00:26227 &digest_algorithm));
Joachim Bauch1b794d52015-05-12 01:32:11228 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
henrike@webrtc.orgf0488722014-05-13 18:00:26229
230 // The test certificate has an MD5-based signature.
231 ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm));
232 ASSERT_EQ(rtc::DIGEST_MD5, digest_algorithm);
233 }
234
Torbjorn Granlundb6d4ec42015-08-17 12:08:59235 typedef unsigned char DigestType[rtc::MessageDigest::kMaxSize];
236
237 void TestDigestHelper(DigestType digest,
238 const SSLIdentity* identity,
239 const std::string& algorithm,
240 size_t expected_len) {
241 DigestType digest1;
242 size_t digest_len;
henrike@webrtc.orgf0488722014-05-13 18:00:26243 bool rv;
244
Torbjorn Granlundb6d4ec42015-08-17 12:08:59245 memset(digest, 0, expected_len);
246 rv = identity->certificate().ComputeDigest(algorithm, digest,
247 sizeof(DigestType), &digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26248 EXPECT_TRUE(rv);
Torbjorn Granlundb6d4ec42015-08-17 12:08:59249 EXPECT_EQ(expected_len, digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26250
Torbjorn Granlundb6d4ec42015-08-17 12:08:59251 // Repeat digest computation for the identity as a sanity check.
252 memset(digest1, 0xff, expected_len);
253 rv = identity->certificate().ComputeDigest(algorithm, digest1,
254 sizeof(DigestType), &digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26255 EXPECT_TRUE(rv);
Torbjorn Granlundb6d4ec42015-08-17 12:08:59256 EXPECT_EQ(expected_len, digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26257
Torbjorn Granlundb6d4ec42015-08-17 12:08:59258 EXPECT_EQ(0, memcmp(digest, digest1, expected_len));
259 }
henrike@webrtc.orgf0488722014-05-13 18:00:26260
Torbjorn Granlundb6d4ec42015-08-17 12:08:59261 void TestDigestForGeneratedCert(const std::string& algorithm,
262 size_t expected_len) {
263 DigestType digest[4];
henrike@webrtc.orgf0488722014-05-13 18:00:26264
Torbjorn Granlundb6d4ec42015-08-17 12:08:59265 ASSERT_TRUE(expected_len <= sizeof(DigestType));
henrike@webrtc.orgf0488722014-05-13 18:00:26266
Torbjorn Granlundb6d4ec42015-08-17 12:08:59267 TestDigestHelper(digest[0], identity_rsa1_.get(), algorithm, expected_len);
268 TestDigestHelper(digest[1], identity_rsa2_.get(), algorithm, expected_len);
269 TestDigestHelper(digest[2], identity_ecdsa1_.get(), algorithm,
270 expected_len);
271 TestDigestHelper(digest[3], identity_ecdsa2_.get(), algorithm,
272 expected_len);
273
274 // Sanity check that all four digests are unique. This could theoretically
275 // fail, since cryptographic hash collisions have a non-zero probability.
276 for (int i = 0; i < 4; i++) {
277 for (int j = 0; j < 4; j++) {
278 if (i != j)
279 EXPECT_NE(0, memcmp(digest[i], digest[j], expected_len));
280 }
henrike@webrtc.orgf0488722014-05-13 18:00:26281 }
282 }
283
Torbjorn Granlundb6d4ec42015-08-17 12:08:59284 void TestDigestForFixedCert(const std::string& algorithm,
285 size_t expected_len,
286 const unsigned char* expected_digest) {
287 bool rv;
288 DigestType digest;
289 size_t digest_len;
290
291 ASSERT_TRUE(expected_len <= sizeof(DigestType));
292
293 rv = test_cert_->ComputeDigest(algorithm, digest, sizeof(digest),
294 &digest_len);
295 EXPECT_TRUE(rv);
296 EXPECT_EQ(expected_len, digest_len);
297 EXPECT_EQ(0, memcmp(digest, expected_digest, expected_len));
298 }
299
hbos6b470a92016-04-28 12:14:21300 void TestCloningIdentity(const SSLIdentity& identity) {
301 // Convert |identity| to PEM strings and create a new identity by converting
302 // back from the string format.
303 std::string priv_pem = identity.PrivateKeyToPEMString();
304 std::string publ_pem = identity.PublicKeyToPEMString();
305 std::string cert_pem = identity.certificate().ToPEMString();
306 std::unique_ptr<SSLIdentity> clone(
307 SSLIdentity::FromPEMStrings(priv_pem, cert_pem));
308 EXPECT_TRUE(clone);
309
310 // Make sure the clone is identical to the original.
311 EXPECT_TRUE(identity == *clone);
312 ASSERT_EQ(identity.certificate().CertificateExpirationTime(),
313 clone->certificate().CertificateExpirationTime());
314
315 // At this point we are confident that the identities are identical. To be
316 // extra sure, we compare PEM strings of the clone with the original. Note
317 // that the PEM strings of two identities are not strictly guaranteed to be
318 // equal (they describe structs whose members could be listed in a different
319 // order, for example). But because the same function is used to produce
320 // both PEMs, its a good enough bet that this comparison will work. If the
321 // assumption stops holding in the future we can always remove this from the
322 // unittest.
323 std::string clone_priv_pem = clone->PrivateKeyToPEMString();
324 std::string clone_publ_pem = clone->PublicKeyToPEMString();
325 std::string clone_cert_pem = clone->certificate().ToPEMString();
326 ASSERT_EQ(priv_pem, clone_priv_pem);
327 ASSERT_EQ(publ_pem, clone_publ_pem);
328 ASSERT_EQ(cert_pem, clone_cert_pem);
329 }
330
331 protected:
jbauch555604a2016-04-26 10:13:22332 std::unique_ptr<SSLIdentity> identity_rsa1_;
333 std::unique_ptr<SSLIdentity> identity_rsa2_;
334 std::unique_ptr<SSLIdentity> identity_ecdsa1_;
335 std::unique_ptr<SSLIdentity> identity_ecdsa2_;
336 std::unique_ptr<rtc::SSLCertificate> test_cert_;
henrike@webrtc.orgf0488722014-05-13 18:00:26337};
338
Torbjorn Granlundb6d4ec42015-08-17 12:08:59339TEST_F(SSLIdentityTest, FixedDigestSHA1) {
340 TestDigestForFixedCert(rtc::DIGEST_SHA_1, 20, kTestCertSha1);
341}
342
343// HASH_AlgSHA224 is not supported in the chromium linux build.
Torbjorn Granlundb6d4ec42015-08-17 12:08:59344TEST_F(SSLIdentityTest, FixedDigestSHA224) {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59345 TestDigestForFixedCert(rtc::DIGEST_SHA_224, 28, kTestCertSha224);
346}
347
348TEST_F(SSLIdentityTest, FixedDigestSHA256) {
349 TestDigestForFixedCert(rtc::DIGEST_SHA_256, 32, kTestCertSha256);
350}
351
352TEST_F(SSLIdentityTest, FixedDigestSHA384) {
353 TestDigestForFixedCert(rtc::DIGEST_SHA_384, 48, kTestCertSha384);
354}
355
356TEST_F(SSLIdentityTest, FixedDigestSHA512) {
357 TestDigestForFixedCert(rtc::DIGEST_SHA_512, 64, kTestCertSha512);
henrike@webrtc.orgf0488722014-05-13 18:00:26358}
359
360// HASH_AlgSHA224 is not supported in the chromium linux build.
henrike@webrtc.orgf0488722014-05-13 18:00:26361TEST_F(SSLIdentityTest, DigestSHA224) {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59362 TestDigestForGeneratedCert(rtc::DIGEST_SHA_224, 28);
henrike@webrtc.orgf0488722014-05-13 18:00:26363}
364
365TEST_F(SSLIdentityTest, DigestSHA256) {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59366 TestDigestForGeneratedCert(rtc::DIGEST_SHA_256, 32);
henrike@webrtc.orgf0488722014-05-13 18:00:26367}
368
369TEST_F(SSLIdentityTest, DigestSHA384) {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59370 TestDigestForGeneratedCert(rtc::DIGEST_SHA_384, 48);
henrike@webrtc.orgf0488722014-05-13 18:00:26371}
372
373TEST_F(SSLIdentityTest, DigestSHA512) {
Torbjorn Granlundb6d4ec42015-08-17 12:08:59374 TestDigestForGeneratedCert(rtc::DIGEST_SHA_512, 64);
henrike@webrtc.orgf0488722014-05-13 18:00:26375}
376
hbos6b470a92016-04-28 12:14:21377TEST_F(SSLIdentityTest, IdentityComparison) {
378 EXPECT_TRUE(*identity_rsa1_ == *identity_rsa1_);
379 EXPECT_FALSE(*identity_rsa1_ == *identity_rsa2_);
380 EXPECT_FALSE(*identity_rsa1_ == *identity_ecdsa1_);
381 EXPECT_FALSE(*identity_rsa1_ == *identity_ecdsa2_);
henrike@webrtc.orgf0488722014-05-13 18:00:26382
hbos6b470a92016-04-28 12:14:21383 EXPECT_TRUE(*identity_rsa2_ == *identity_rsa2_);
384 EXPECT_FALSE(*identity_rsa2_ == *identity_ecdsa1_);
385 EXPECT_FALSE(*identity_rsa2_ == *identity_ecdsa2_);
386
387 EXPECT_TRUE(*identity_ecdsa1_ == *identity_ecdsa1_);
388 EXPECT_FALSE(*identity_ecdsa1_ == *identity_ecdsa2_);
389}
390
391TEST_F(SSLIdentityTest, FromPEMStringsRSA) {
jbauch555604a2016-04-26 10:13:22392 std::unique_ptr<SSLIdentity> identity(
hbose29352b2016-08-25 10:52:38393 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kRSA_CERT_PEM));
henrike@webrtc.orgf0488722014-05-13 18:00:26394 EXPECT_TRUE(identity);
hbos6b470a92016-04-28 12:14:21395 EXPECT_EQ(kRSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
396 EXPECT_EQ(kRSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
hbose29352b2016-08-25 10:52:38397 EXPECT_EQ(kRSA_CERT_PEM, identity->certificate().ToPEMString());
henrike@webrtc.orgf0488722014-05-13 18:00:26398}
399
Torbjorn Granlundb6d4ec42015-08-17 12:08:59400TEST_F(SSLIdentityTest, FromPEMStringsEC) {
jbauch555604a2016-04-26 10:13:22401 std::unique_ptr<SSLIdentity> identity(
hbose29352b2016-08-25 10:52:38402 SSLIdentity::FromPEMStrings(kECDSA_PRIVATE_KEY_PEM, kECDSA_CERT_PEM));
Torbjorn Granlundb6d4ec42015-08-17 12:08:59403 EXPECT_TRUE(identity);
hbos6b470a92016-04-28 12:14:21404 EXPECT_EQ(kECDSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
405 EXPECT_EQ(kECDSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
hbose29352b2016-08-25 10:52:38406 EXPECT_EQ(kECDSA_CERT_PEM, identity->certificate().ToPEMString());
Torbjorn Granlundb6d4ec42015-08-17 12:08:59407}
Torbjorn Granlundb6d4ec42015-08-17 12:08:59408
hbos6b470a92016-04-28 12:14:21409TEST_F(SSLIdentityTest, CloneIdentityRSA) {
410 TestCloningIdentity(*identity_rsa1_);
411 TestCloningIdentity(*identity_rsa2_);
412}
413
414TEST_F(SSLIdentityTest, CloneIdentityECDSA) {
415 TestCloningIdentity(*identity_ecdsa1_);
416 TestCloningIdentity(*identity_ecdsa2_);
417}
418
henrike@webrtc.orgf0488722014-05-13 18:00:26419TEST_F(SSLIdentityTest, PemDerConversion) {
420 std::string der;
421 EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der));
422
Yves Gerey665174f2018-06-19 13:03:05423 EXPECT_EQ(
424 kTestCertificate,
425 SSLIdentity::DerToPem("CERTIFICATE",
426 reinterpret_cast<const unsigned char*>(der.data()),
427 der.length()));
henrike@webrtc.orgf0488722014-05-13 18:00:26428}
429
430TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) {
431 TestGetSignatureDigestAlgorithm();
432}
Torbjorn Granlund46c9cc02015-12-01 12:06:34433
hbose29352b2016-08-25 10:52:38434TEST_F(SSLIdentityTest, SSLCertificateGetStatsRSA) {
435 std::unique_ptr<SSLIdentity> identity(
436 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kRSA_CERT_PEM));
437 std::unique_ptr<rtc::SSLCertificateStats> stats =
438 identity->certificate().GetStats();
439 EXPECT_EQ(stats->fingerprint, kRSA_FINGERPRINT);
440 EXPECT_EQ(stats->fingerprint_algorithm, kRSA_FINGERPRINT_ALGORITHM);
441 EXPECT_EQ(stats->base64_certificate, kRSA_BASE64_CERTIFICATE);
442 EXPECT_FALSE(stats->issuer);
443}
444
445TEST_F(SSLIdentityTest, SSLCertificateGetStatsECDSA) {
446 std::unique_ptr<SSLIdentity> identity(
447 SSLIdentity::FromPEMStrings(kECDSA_PRIVATE_KEY_PEM, kECDSA_CERT_PEM));
448 std::unique_ptr<rtc::SSLCertificateStats> stats =
449 identity->certificate().GetStats();
450 EXPECT_EQ(stats->fingerprint, kECDSA_FINGERPRINT);
451 EXPECT_EQ(stats->fingerprint_algorithm, kECDSA_FINGERPRINT_ALGORITHM);
452 EXPECT_EQ(stats->base64_certificate, kECDSA_BASE64_CERTIFICATE);
453 EXPECT_FALSE(stats->issuer);
454}
455
456TEST_F(SSLIdentityTest, SSLCertificateGetStatsWithChain) {
457 std::vector<std::string> ders;
458 ders.push_back("every der results in");
459 ders.push_back("an identity + certificate");
460 ders.push_back("in a certificate chain");
461 IdentityAndInfo info = CreateFakeIdentityAndInfoFromDers(ders);
462 EXPECT_TRUE(info.identity);
463 EXPECT_EQ(info.ders, ders);
464 EXPECT_EQ(info.pems.size(), info.ders.size());
465 EXPECT_EQ(info.fingerprints.size(), info.ders.size());
466
467 std::unique_ptr<rtc::SSLCertificateStats> first_stats =
Taylor Brandstetterc3928662018-02-23 21:04:51468 info.identity->cert_chain().GetStats();
hbose29352b2016-08-25 10:52:38469 rtc::SSLCertificateStats* cert_stats = first_stats.get();
470 for (size_t i = 0; i < info.ders.size(); ++i) {
471 EXPECT_EQ(cert_stats->fingerprint, info.fingerprints[i]);
472 EXPECT_EQ(cert_stats->fingerprint_algorithm, "sha-1");
473 EXPECT_EQ(cert_stats->base64_certificate, info.pems[i]);
474 cert_stats = cert_stats->issuer.get();
475 EXPECT_EQ(static_cast<bool>(cert_stats), i + 1 < info.ders.size());
476 }
477}
478
Mirko Bonadei6a489f22019-04-09 13:11:12479class SSLIdentityExpirationTest : public ::testing::Test {
Torbjorn Granlund46c9cc02015-12-01 12:06:34480 public:
481 SSLIdentityExpirationTest() {
482 // Set use of the test RNG to get deterministic expiration timestamp.
483 rtc::SetRandomTestMode(true);
484 }
Steve Anton9de3aac2017-10-24 17:08:26485 ~SSLIdentityExpirationTest() override {
Torbjorn Granlund46c9cc02015-12-01 12:06:34486 // Put it back for the next test.
487 rtc::SetRandomTestMode(false);
488 }
489
490 void TestASN1TimeToSec() {
491 struct asn_example {
492 const char* string;
493 bool long_format;
494 int64_t want;
495 } static const data[] = {
Yves Gerey665174f2018-06-19 13:03:05496 // clang-format off
497 // clang formatting breaks this nice alignment
498
Torbjorn Granlund46c9cc02015-12-01 12:06:34499 // Valid examples.
500 {"19700101000000Z", true, 0},
501 {"700101000000Z", false, 0},
502 {"19700101000001Z", true, 1},
503 {"700101000001Z", false, 1},
504 {"19700101000100Z", true, 60},
505 {"19700101000101Z", true, 61},
506 {"19700101010000Z", true, 3600},
507 {"19700101010001Z", true, 3601},
508 {"19700101010100Z", true, 3660},
509 {"19700101010101Z", true, 3661},
510 {"710911012345Z", false, 53400225},
511 {"20000101000000Z", true, 946684800},
512 {"20000101000000Z", true, 946684800},
513 {"20151130140156Z", true, 1448892116},
514 {"151130140156Z", false, 1448892116},
515 {"20491231235959Z", true, 2524607999},
516 {"491231235959Z", false, 2524607999},
517 {"20500101000000Z", true, 2524607999+1},
518 {"20700101000000Z", true, 3155760000},
519 {"21000101000000Z", true, 4102444800},
520 {"24000101000000Z", true, 13569465600},
521
522 // Invalid examples.
523 {"19700101000000", true, -1}, // missing Z long format
524 {"19700101000000X", true, -1}, // X instead of Z long format
525 {"197001010000000", true, -1}, // 0 instead of Z long format
526 {"1970010100000000Z", true, -1}, // excess digits long format
527 {"700101000000", false, -1}, // missing Z short format
528 {"700101000000X", false, -1}, // X instead of Z short format
529 {"7001010000000", false, -1}, // 0 instead of Z short format
530 {"70010100000000Z", false, -1}, // excess digits short format
531 {":9700101000000Z", true, -1}, // invalid character
532 {"1:700101000001Z", true, -1}, // invalid character
533 {"19:00101000100Z", true, -1}, // invalid character
534 {"197:0101000101Z", true, -1}, // invalid character
535 {"1970:101010000Z", true, -1}, // invalid character
536 {"19700:01010001Z", true, -1}, // invalid character
537 {"197001:1010100Z", true, -1}, // invalid character
538 {"1970010:010101Z", true, -1}, // invalid character
539 {"70010100:000Z", false, -1}, // invalid character
540 {"700101000:01Z", false, -1}, // invalid character
541 {"2000010100:000Z", true, -1}, // invalid character
542 {"21000101000:00Z", true, -1}, // invalid character
543 {"240001010000:0Z", true, -1}, // invalid character
544 {"500101000000Z", false, -1}, // but too old for epoch
545 {"691231235959Z", false, -1}, // too old for epoch
546 {"19611118043000Z", false, -1}, // way too old for epoch
Yves Gerey665174f2018-06-19 13:03:05547
548 // clang-format off
Torbjorn Granlund46c9cc02015-12-01 12:06:34549 };
550
551 unsigned char buf[20];
552
553 // Run all examples and check for the expected result.
554 for (const auto& entry : data) {
555 size_t length = strlen(entry.string);
556 memcpy(buf, entry.string, length); // Copy the ASN1 string...
557 buf[length] = rtc::CreateRandomId(); // ...and terminate it with junk.
558 int64_t res = rtc::ASN1TimeToSec(buf, length, entry.long_format);
Mirko Bonadei675513b2017-11-09 10:09:25559 RTC_LOG(LS_VERBOSE) << entry.string;
Torbjorn Granlund46c9cc02015-12-01 12:06:34560 ASSERT_EQ(entry.want, res);
561 }
562 // Run all examples again, but with an invalid length.
563 for (const auto& entry : data) {
564 size_t length = strlen(entry.string);
565 memcpy(buf, entry.string, length); // Copy the ASN1 string...
566 buf[length] = rtc::CreateRandomId(); // ...and terminate it with junk.
567 int64_t res = rtc::ASN1TimeToSec(buf, length - 1, entry.long_format);
Mirko Bonadei675513b2017-11-09 10:09:25568 RTC_LOG(LS_VERBOSE) << entry.string;
Torbjorn Granlund46c9cc02015-12-01 12:06:34569 ASSERT_EQ(-1, res);
570 }
571 }
572
573 void TestExpireTime(int times) {
torbjornge8dc0812016-02-15 17:35:54574 // We test just ECDSA here since what we're out to exercise is the
575 // interfaces for expiration setting and reading.
Torbjorn Granlund46c9cc02015-12-01 12:06:34576 for (int i = 0; i < times; i++) {
Torbjorn Granlund46c9cc02015-12-01 12:06:34577 // We limit the time to < 2^31 here, i.e., we stay before 2038, since else
578 // we hit time offset limitations in OpenSSL on some 32-bit systems.
Taylor Brandstetter88dec832016-03-15 16:57:55579 time_t time_before_generation = time(nullptr);
580 time_t lifetime =
581 rtc::CreateRandomId() % (0x80000000 - time_before_generation);
torbjornge8dc0812016-02-15 17:35:54582 rtc::KeyParams key_params = rtc::KeyParams::ECDSA(rtc::EC_NIST_P256);
583 SSLIdentity* identity =
Torbjorn Granlund1d846b22016-03-31 14:21:04584 rtc::SSLIdentity::GenerateWithExpiration("", key_params, lifetime);
Taylor Brandstetter88dec832016-03-15 16:57:55585 time_t time_after_generation = time(nullptr);
586 EXPECT_LE(time_before_generation + lifetime,
587 identity->certificate().CertificateExpirationTime());
588 EXPECT_GE(time_after_generation + lifetime,
Torbjorn Granlund46c9cc02015-12-01 12:06:34589 identity->certificate().CertificateExpirationTime());
590 delete identity;
591 }
592 }
593};
594
595TEST_F(SSLIdentityExpirationTest, TestASN1TimeToSec) {
596 TestASN1TimeToSec();
597}
598
599TEST_F(SSLIdentityExpirationTest, TestExpireTime) {
600 TestExpireTime(500);
601}