blob: 1f0278ac7109da1ca90cc79c91529e55bcc43c2e [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Ali Tofigh7fa90572022-03-17 15:47:49 +010011#include "rtc_base/ssl_identity.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Ali Tofigh7fa90572022-03-17 15:47:49 +010014
jbauch555604a2016-04-26 03:13:22 -070015#include <memory>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000016#include <string>
Yves Gerey3e707812018-11-28 16:47:49 +010017#include <vector>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018
Steve Anton1c9c9fc2019-02-14 15:13:09 -080019#include "absl/strings/str_replace.h"
Ali Tofigh7fa90572022-03-17 15:47:49 +010020#include "absl/strings/string_view.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/fake_ssl_identity.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/helpers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/message_digest.h"
26#include "rtc_base/ssl_fingerprint.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "test/gtest.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000028
29using rtc::SSLIdentity;
30
Yves Gerey665174f2018-06-19 15:03:05 +020031const char kTestCertificate[] =
32 "-----BEGIN CERTIFICATE-----\n"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033 "MIIB6TCCAVICAQYwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV\n"
34 "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD\n"
35 "VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDAxMDE2MjIzMTAzWhcNMDMwMTE0\n"
36 "MjIzMTAzWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG\n"
37 "A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNl\n"
38 "cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIP\n"
39 "Fe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2//\n"
40 "Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCT0grFQeZaqYb5EYfk20XixZV4\n"
41 "GmyAbXMftG1Eo7qGiMhYzRwGNWxEYojf5PZkYZXvSqZ/ZXHXa4g59jK/rJNnaVGM\n"
42 "k+xIX8mxQvlV0n5O9PIha5BX5teZnkHKgL8aKKLKW1BK7YTngsfSzzaeame5iKfz\n"
43 "itAE+OjGF+PFKbwX8Q==\n"
44 "-----END CERTIFICATE-----\n";
45
Yves Gerey665174f2018-06-19 15:03:05 +020046const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA, 0xC3, 0x7E, 0x6D,
47 0x33, 0xCF, 0xE2, 0x69, 0x9D, 0x74, 0xE6,
48 0xF6, 0x8A, 0x9E, 0x47, 0xA7, 0xCA};
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +020049const unsigned char kTestCertSha224[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020050 0xd4, 0xce, 0xc6, 0xcf, 0x28, 0xcb, 0xe9, 0x77, 0x38, 0x36,
51 0xcf, 0xb1, 0x3b, 0x4a, 0xd7, 0xbd, 0xae, 0x24, 0x21, 0x08,
52 0xcf, 0x6a, 0x44, 0x0d, 0x3f, 0x94, 0x2a, 0x5b};
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +020053const unsigned char kTestCertSha256[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020054 0x41, 0x6b, 0xb4, 0x93, 0x47, 0x79, 0x77, 0x24, 0x77, 0x0b, 0x8b,
55 0x2e, 0xa6, 0x2b, 0xe0, 0xf9, 0x0a, 0xed, 0x1f, 0x31, 0xa6, 0xf7,
56 0x5c, 0xa1, 0x5a, 0xc4, 0xb0, 0xa2, 0xa4, 0x78, 0xb9, 0x76};
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +020057const unsigned char kTestCertSha384[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020058 0x42, 0x31, 0x9a, 0x79, 0x1d, 0xd6, 0x08, 0xbf, 0x3b, 0xba, 0x36, 0xd8,
59 0x37, 0x4a, 0x9a, 0x75, 0xd3, 0x25, 0x6e, 0x28, 0x92, 0xbe, 0x06, 0xb7,
60 0xc5, 0xa0, 0x83, 0xe3, 0x86, 0xb1, 0x03, 0xfc, 0x64, 0x47, 0xd6, 0xd8,
61 0xaa, 0xd9, 0x36, 0x60, 0x04, 0xcc, 0xbe, 0x7d, 0x6a, 0xe8, 0x34, 0x49};
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +020062const unsigned char kTestCertSha512[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020063 0x51, 0x1d, 0xec, 0x02, 0x3d, 0x51, 0x45, 0xd3, 0xd8, 0x1d, 0xa4,
64 0x9d, 0x43, 0xc9, 0xee, 0x32, 0x6f, 0x4f, 0x37, 0xee, 0xab, 0x3f,
65 0x25, 0xdf, 0x72, 0xfc, 0x61, 0x1a, 0xd5, 0x92, 0xff, 0x6b, 0x28,
66 0x71, 0x58, 0xb3, 0xe1, 0x8a, 0x18, 0xcf, 0x61, 0x33, 0x0e, 0x14,
67 0xc3, 0x04, 0xaa, 0x07, 0xf6, 0xa5, 0xda, 0xdc, 0x42, 0x42, 0x22,
68 0x35, 0xce, 0x26, 0x58, 0x4a, 0x33, 0x6d, 0xbc, 0xb6};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069
hbose29352b2016-08-25 03:52:38 -070070// These PEM strings were created by generating an identity with
Artem Titovcfea2182021-08-10 01:22:31 +020071// `SSLIdentity::Create` and invoking `identity->PrivateKeyToPEMString()`,
72// `identity->PublicKeyToPEMString()` and
73// `identity->certificate().ToPEMString()`. If the crypto library is updated,
hbose29352b2016-08-25 03:52:38 -070074// and the update changes the string form of the keys, these will have to be
75// updated too. The fingerprint, fingerprint algorithm and base64 certificate
Artem Titovcfea2182021-08-10 01:22:31 +020076// were created by calling `identity->certificate().GetStats()`.
hbose29352b2016-08-25 03:52:38 -070077static const char kRSA_PRIVATE_KEY_PEM[] =
78 "-----BEGIN PRIVATE KEY-----\n"
79 "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMQPqDStRlYeDpkX\n"
80 "erRmv+a1naM8vSVSY0gG2plnrnofViWRW3MRqWC+020MsIj3hPZeSAnt/y/FL/nr\n"
81 "4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHwcFcMr31HLFvHr0ZgcFwbgIuFLNEl\n"
82 "7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAECgYA8FWBC5GcNtSBcIinkZyigF0A7\n"
83 "6j081sa+J/uNz4xUuI257ZXM6biygUhhvuXK06/XoIULJfhyN0fAm1yb0HtNhiUs\n"
84 "kMOYeon6b8FqFaPjrQf7Gr9FMiIHXNK19uegTMKztXyPZoUWlX84X0iawY95x0Y3\n"
85 "73f6P2rN2UOjlVVjAQJBAOKy3l2w3Zj2w0oAJox0eMwl+RxBNt1C42SHrob2mFUT\n"
86 "rytpVVYOasr8CoDI0kjacjI94sLum+buJoXXX6YTGO0CQQDdZwlYIEkoS3ftfxPa\n"
87 "Ai0YTBzAWvHJg0r8Gk/TkHo6IM+LSsZ9ZYUv/vBe4BKLw1I4hZ+bQvBiq+f8ROtk\n"
88 "+TDRAkAPL3ghwoU1h+IRBO2QHwUwd6K2N9AbBi4BP+168O3HVSg4ujeTKigRLMzv\n"
89 "T4R2iNt5bhfQgvdCgtVlxcWMdF8JAkBwDCg3eEdt5BuyjwBt8XH+/O4ED0KUWCTH\n"
90 "x00k5dZlupsuhE5Fwe4QpzXg3gekwdnHjyCCQ/NCDHvgOMTkmhQxAkA9V03KRX9b\n"
91 "bhvEzY/fu8gEp+EzsER96/D79az5z1BaMGL5OPM2xHBPJATKlswnAa7Lp3QKGZGk\n"
92 "TxslfL18J71s\n"
93 "-----END PRIVATE KEY-----\n";
94static const char kRSA_PUBLIC_KEY_PEM[] =
95 "-----BEGIN PUBLIC KEY-----\n"
96 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDED6g0rUZWHg6ZF3q0Zr/mtZ2j\n"
97 "PL0lUmNIBtqZZ656H1YlkVtzEalgvtNtDLCI94T2XkgJ7f8vxS/56+BGuzV3MHUa\n"
98 "Nf9cRCu1P3/3I0oNWrp8rxwh8HBXDK99Ryxbx69GYHBcG4CLhSzRJe5CuRzDvQD8\n"
99 "9Z7VI3pPAZgY/MjJfQIDAQAB\n"
100 "-----END PUBLIC KEY-----\n";
101static const char kRSA_CERT_PEM[] =
102 "-----BEGIN CERTIFICATE-----\n"
103 "MIIBnDCCAQWgAwIBAgIJAOEHLgeWYwrpMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNV\n"
104 "BAMMBXRlc3QxMB4XDTE2MDQyNDE4MTAyMloXDTE2MDUyNTE4MTAyMlowEDEOMAwG\n"
105 "A1UEAwwFdGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQPqDStRlYe\n"
106 "DpkXerRmv+a1naM8vSVSY0gG2plnrnofViWRW3MRqWC+020MsIj3hPZeSAnt/y/F\n"
107 "L/nr4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHwcFcMr31HLFvHr0ZgcFwbgIuF\n"
108 "LNEl7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAEwDQYJKoZIhvcNAQELBQADgYEA\n"
109 "C3ehaZFl+oEYN069C2ht/gMzuC77L854RF/x7xRtNZzkcg9TVgXXdM3auUvJi8dx\n"
110 "yTpU3ixErjQvoZew5ngXTEvTY8BSQUijJEaLWh8n6NDKRbEGTdAk8nPAmq9hdCFq\n"
111 "e3UkexqNHm3g/VxG4NUC1Y+w29ai0/Rgh+VvgbDwK+Q=\n"
112 "-----END CERTIFICATE-----\n";
113static const char kRSA_FINGERPRINT[] =
114 "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"
115 ":2A:EE:F9:9A:DD:E2:2B";
Yves Gerey665174f2018-06-19 15:03:05 +0200116static const char kRSA_FINGERPRINT_ALGORITHM[] = "sha-256";
hbose29352b2016-08-25 03:52:38 -0700117static const char kRSA_BASE64_CERTIFICATE[] =
118 "MIIBnDCCAQWgAwIBAgIJAOEHLgeWYwrpMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNVBAMMBXRlc3"
119 "QxMB4XDTE2MDQyNDE4MTAyMloXDTE2MDUyNTE4MTAyMlowEDEOMAwGA1UEAwwFdGVzdDEwgZ8w"
120 "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQPqDStRlYeDpkXerRmv+a1naM8vSVSY0gG2plnrn"
121 "ofViWRW3MRqWC+020MsIj3hPZeSAnt/y/FL/nr4Ea7NXcwdRo1/1xEK7U/f/cjSg1aunyvHCHw"
122 "cFcMr31HLFvHr0ZgcFwbgIuFLNEl7kK5HMO9APz1ntUjek8BmBj8yMl9AgMBAAEwDQYJKoZIhv"
123 "cNAQELBQADgYEAC3ehaZFl+oEYN069C2ht/gMzuC77L854RF/x7xRtNZzkcg9TVgXXdM3auUvJ"
124 "i8dxyTpU3ixErjQvoZew5ngXTEvTY8BSQUijJEaLWh8n6NDKRbEGTdAk8nPAmq9hdCFqe3Ukex"
125 "qNHm3g/VxG4NUC1Y+w29ai0/Rgh+VvgbDwK+Q=";
126
127static const char kECDSA_PRIVATE_KEY_PEM[] =
128 "-----BEGIN PRIVATE KEY-----\n"
129 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/AkEA2hklq7dQ2rN\n"
130 "ZxYL6hOUACL4pn7P4FYlA3ZQhIChRANCAAR7YgdO3utP/8IqVRq8G4VZKreMAxeN\n"
131 "rUa12twthv4uFjuHAHa9D9oyAjncmn+xvZZRyVmKrA56jRzENcEEHoAg\n"
132 "-----END PRIVATE KEY-----\n";
133static const char kECDSA_PUBLIC_KEY_PEM[] =
134 "-----BEGIN PUBLIC KEY-----\n"
135 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEe2IHTt7rT//CKlUavBuFWSq3jAMX\n"
136 "ja1GtdrcLYb+LhY7hwB2vQ/aMgI53Jp/sb2WUclZiqwOeo0cxDXBBB6AIA==\n"
137 "-----END PUBLIC KEY-----\n";
138static const char kECDSA_CERT_PEM[] =
139 "-----BEGIN CERTIFICATE-----\n"
140 "MIIBFDCBu6ADAgECAgkArpkxjw62sW4wCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
141 "dGVzdDMwHhcNMTYwNDI0MTgxNDM4WhcNMTYwNTI1MTgxNDM4WjAQMQ4wDAYDVQQD\n"
142 "DAV0ZXN0MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHtiB07e60//wipVGrwb\n"
143 "hVkqt4wDF42tRrXa3C2G/i4WO4cAdr0P2jICOdyaf7G9llHJWYqsDnqNHMQ1wQQe\n"
144 "gCAwCgYIKoZIzj0EAwIDSAAwRQIhANyreQ/K5yuPPpirsd0e/4WGLHou6bIOSQks\n"
145 "DYzo56NmAiAKOr3u8ol3LmygbUCwEvtWrS8QcJDygxHPACo99hkekw==\n"
146 "-----END CERTIFICATE-----\n";
147static const char kECDSA_FINGERPRINT[] =
148 "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"
149 ":50:33:A9:FF:4D:31:89";
Yves Gerey665174f2018-06-19 15:03:05 +0200150static const char kECDSA_FINGERPRINT_ALGORITHM[] = "sha-256";
hbose29352b2016-08-25 03:52:38 -0700151static const char kECDSA_BASE64_CERTIFICATE[] =
152 "MIIBFDCBu6ADAgECAgkArpkxjw62sW4wCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwFdGVzdDMwHh"
153 "cNMTYwNDI0MTgxNDM4WhcNMTYwNTI1MTgxNDM4WjAQMQ4wDAYDVQQDDAV0ZXN0MzBZMBMGByqG"
154 "SM49AgEGCCqGSM49AwEHA0IABHtiB07e60//wipVGrwbhVkqt4wDF42tRrXa3C2G/i4WO4cAdr"
155 "0P2jICOdyaf7G9llHJWYqsDnqNHMQ1wQQegCAwCgYIKoZIzj0EAwIDSAAwRQIhANyreQ/K5yuP"
156 "Ppirsd0e/4WGLHou6bIOSQksDYzo56NmAiAKOr3u8ol3LmygbUCwEvtWrS8QcJDygxHPACo99h"
157 "kekw==";
158
159struct IdentityAndInfo {
160 std::unique_ptr<rtc::SSLIdentity> identity;
161 std::vector<std::string> ders;
162 std::vector<std::string> pems;
163 std::vector<std::string> fingerprints;
164};
165
166IdentityAndInfo CreateFakeIdentityAndInfoFromDers(
167 const std::vector<std::string>& ders) {
168 RTC_CHECK(!ders.empty());
169 IdentityAndInfo info;
170 info.ders = ders;
171 for (const std::string& der : ders) {
172 info.pems.push_back(rtc::SSLIdentity::DerToPem(
Yves Gerey665174f2018-06-19 15:03:05 +0200173 "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
hbose29352b2016-08-25 03:52:38 -0700174 der.length()));
175 }
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800176 info.identity.reset(new rtc::FakeSSLIdentity(info.pems));
hbose29352b2016-08-25 03:52:38 -0700177 // Strip header/footer and newline characters of PEM strings.
178 for (size_t i = 0; i < info.pems.size(); ++i) {
Steve Anton1c9c9fc2019-02-14 15:13:09 -0800179 absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
180 {"-----END CERTIFICATE-----", ""},
181 {"\n", ""}},
182 &info.pems[i]);
hbose29352b2016-08-25 03:52:38 -0700183 }
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800184 // Fingerprints for the whole certificate chain, starting with leaf
185 // certificate.
186 const rtc::SSLCertChain& chain = info.identity->cert_chain();
187 std::unique_ptr<rtc::SSLFingerprint> fp;
188 for (size_t i = 0; i < chain.GetSize(); i++) {
Steve Anton4905edb2018-10-15 19:27:44 -0700189 fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800190 EXPECT_TRUE(fp);
191 info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
hbose29352b2016-08-25 03:52:38 -0700192 }
193 EXPECT_EQ(info.ders.size(), info.fingerprints.size());
194 return info;
195}
196
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200197class SSLIdentityTest : public ::testing::Test {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000198 public:
Steve Anton9de3aac2017-10-24 10:08:26 -0700199 void SetUp() override {
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100200 identity_rsa1_ = SSLIdentity::Create("test1", rtc::KT_RSA);
201 identity_rsa2_ = SSLIdentity::Create("test2", rtc::KT_RSA);
202 identity_ecdsa1_ = SSLIdentity::Create("test3", rtc::KT_ECDSA);
203 identity_ecdsa2_ = SSLIdentity::Create("test4", rtc::KT_ECDSA);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000204
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200205 ASSERT_TRUE(identity_rsa1_);
206 ASSERT_TRUE(identity_rsa2_);
207 ASSERT_TRUE(identity_ecdsa1_);
208 ASSERT_TRUE(identity_ecdsa2_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000209
Steve Antonf25303e2018-10-16 15:23:31 -0700210 test_cert_ = rtc::SSLCertificate::FromPEMString(kTestCertificate);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000211 ASSERT_TRUE(test_cert_);
212 }
213
214 void TestGetSignatureDigestAlgorithm() {
215 std::string digest_algorithm;
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200216
217 ASSERT_TRUE(identity_rsa1_->certificate().GetSignatureDigestAlgorithm(
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000218 &digest_algorithm));
Joachim Bauch1b794d52015-05-12 03:32:11 +0200219 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200220
221 ASSERT_TRUE(identity_rsa2_->certificate().GetSignatureDigestAlgorithm(
222 &digest_algorithm));
223 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
224
225 ASSERT_TRUE(identity_ecdsa1_->certificate().GetSignatureDigestAlgorithm(
226 &digest_algorithm));
227 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
228
229 ASSERT_TRUE(identity_ecdsa2_->certificate().GetSignatureDigestAlgorithm(
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000230 &digest_algorithm));
Joachim Bauch1b794d52015-05-12 03:32:11 +0200231 ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000232
233 // The test certificate has an MD5-based signature.
234 ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm));
235 ASSERT_EQ(rtc::DIGEST_MD5, digest_algorithm);
236 }
237
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200238 typedef unsigned char DigestType[rtc::MessageDigest::kMaxSize];
239
240 void TestDigestHelper(DigestType digest,
241 const SSLIdentity* identity,
Ali Tofigh7fa90572022-03-17 15:47:49 +0100242 absl::string_view algorithm,
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200243 size_t expected_len) {
244 DigestType digest1;
245 size_t digest_len;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000246 bool rv;
247
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200248 memset(digest, 0, expected_len);
249 rv = identity->certificate().ComputeDigest(algorithm, digest,
250 sizeof(DigestType), &digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251 EXPECT_TRUE(rv);
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200252 EXPECT_EQ(expected_len, digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000253
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200254 // Repeat digest computation for the identity as a sanity check.
255 memset(digest1, 0xff, expected_len);
256 rv = identity->certificate().ComputeDigest(algorithm, digest1,
257 sizeof(DigestType), &digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000258 EXPECT_TRUE(rv);
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200259 EXPECT_EQ(expected_len, digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000260
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200261 EXPECT_EQ(0, memcmp(digest, digest1, expected_len));
262 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263
Ali Tofigh7fa90572022-03-17 15:47:49 +0100264 void TestDigestForGeneratedCert(absl::string_view algorithm,
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200265 size_t expected_len) {
266 DigestType digest[4];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000267
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200268 ASSERT_TRUE(expected_len <= sizeof(DigestType));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000269
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200270 TestDigestHelper(digest[0], identity_rsa1_.get(), algorithm, expected_len);
271 TestDigestHelper(digest[1], identity_rsa2_.get(), algorithm, expected_len);
272 TestDigestHelper(digest[2], identity_ecdsa1_.get(), algorithm,
273 expected_len);
274 TestDigestHelper(digest[3], identity_ecdsa2_.get(), algorithm,
275 expected_len);
276
277 // Sanity check that all four digests are unique. This could theoretically
278 // fail, since cryptographic hash collisions have a non-zero probability.
279 for (int i = 0; i < 4; i++) {
280 for (int j = 0; j < 4; j++) {
281 if (i != j)
282 EXPECT_NE(0, memcmp(digest[i], digest[j], expected_len));
283 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000284 }
285 }
286
Ali Tofigh7fa90572022-03-17 15:47:49 +0100287 void TestDigestForFixedCert(absl::string_view algorithm,
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200288 size_t expected_len,
289 const unsigned char* expected_digest) {
290 bool rv;
291 DigestType digest;
292 size_t digest_len;
293
294 ASSERT_TRUE(expected_len <= sizeof(DigestType));
295
296 rv = test_cert_->ComputeDigest(algorithm, digest, sizeof(digest),
297 &digest_len);
298 EXPECT_TRUE(rv);
299 EXPECT_EQ(expected_len, digest_len);
300 EXPECT_EQ(0, memcmp(digest, expected_digest, expected_len));
301 }
302
hbos6b470a92016-04-28 05:14:21 -0700303 void TestCloningIdentity(const SSLIdentity& identity) {
Artem Titov96e3b992021-07-26 16:03:14 +0200304 // Convert `identity` to PEM strings and create a new identity by converting
hbos6b470a92016-04-28 05:14:21 -0700305 // back from the string format.
306 std::string priv_pem = identity.PrivateKeyToPEMString();
307 std::string publ_pem = identity.PublicKeyToPEMString();
308 std::string cert_pem = identity.certificate().ToPEMString();
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100309 std::unique_ptr<SSLIdentity> clone =
310 SSLIdentity::CreateFromPEMStrings(priv_pem, cert_pem);
hbos6b470a92016-04-28 05:14:21 -0700311 EXPECT_TRUE(clone);
312
313 // Make sure the clone is identical to the original.
314 EXPECT_TRUE(identity == *clone);
315 ASSERT_EQ(identity.certificate().CertificateExpirationTime(),
316 clone->certificate().CertificateExpirationTime());
317
318 // At this point we are confident that the identities are identical. To be
319 // extra sure, we compare PEM strings of the clone with the original. Note
320 // that the PEM strings of two identities are not strictly guaranteed to be
321 // equal (they describe structs whose members could be listed in a different
322 // order, for example). But because the same function is used to produce
323 // both PEMs, its a good enough bet that this comparison will work. If the
324 // assumption stops holding in the future we can always remove this from the
325 // unittest.
326 std::string clone_priv_pem = clone->PrivateKeyToPEMString();
327 std::string clone_publ_pem = clone->PublicKeyToPEMString();
328 std::string clone_cert_pem = clone->certificate().ToPEMString();
329 ASSERT_EQ(priv_pem, clone_priv_pem);
330 ASSERT_EQ(publ_pem, clone_publ_pem);
331 ASSERT_EQ(cert_pem, clone_cert_pem);
332 }
333
334 protected:
jbauch555604a2016-04-26 03:13:22 -0700335 std::unique_ptr<SSLIdentity> identity_rsa1_;
336 std::unique_ptr<SSLIdentity> identity_rsa2_;
337 std::unique_ptr<SSLIdentity> identity_ecdsa1_;
338 std::unique_ptr<SSLIdentity> identity_ecdsa2_;
339 std::unique_ptr<rtc::SSLCertificate> test_cert_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000340};
341
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200342TEST_F(SSLIdentityTest, FixedDigestSHA1) {
343 TestDigestForFixedCert(rtc::DIGEST_SHA_1, 20, kTestCertSha1);
344}
345
346// HASH_AlgSHA224 is not supported in the chromium linux build.
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200347TEST_F(SSLIdentityTest, FixedDigestSHA224) {
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200348 TestDigestForFixedCert(rtc::DIGEST_SHA_224, 28, kTestCertSha224);
349}
350
351TEST_F(SSLIdentityTest, FixedDigestSHA256) {
352 TestDigestForFixedCert(rtc::DIGEST_SHA_256, 32, kTestCertSha256);
353}
354
355TEST_F(SSLIdentityTest, FixedDigestSHA384) {
356 TestDigestForFixedCert(rtc::DIGEST_SHA_384, 48, kTestCertSha384);
357}
358
359TEST_F(SSLIdentityTest, FixedDigestSHA512) {
360 TestDigestForFixedCert(rtc::DIGEST_SHA_512, 64, kTestCertSha512);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000361}
362
363// HASH_AlgSHA224 is not supported in the chromium linux build.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000364TEST_F(SSLIdentityTest, DigestSHA224) {
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200365 TestDigestForGeneratedCert(rtc::DIGEST_SHA_224, 28);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000366}
367
368TEST_F(SSLIdentityTest, DigestSHA256) {
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200369 TestDigestForGeneratedCert(rtc::DIGEST_SHA_256, 32);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370}
371
372TEST_F(SSLIdentityTest, DigestSHA384) {
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200373 TestDigestForGeneratedCert(rtc::DIGEST_SHA_384, 48);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000374}
375
376TEST_F(SSLIdentityTest, DigestSHA512) {
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200377 TestDigestForGeneratedCert(rtc::DIGEST_SHA_512, 64);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000378}
379
hbos6b470a92016-04-28 05:14:21 -0700380TEST_F(SSLIdentityTest, IdentityComparison) {
381 EXPECT_TRUE(*identity_rsa1_ == *identity_rsa1_);
382 EXPECT_FALSE(*identity_rsa1_ == *identity_rsa2_);
383 EXPECT_FALSE(*identity_rsa1_ == *identity_ecdsa1_);
384 EXPECT_FALSE(*identity_rsa1_ == *identity_ecdsa2_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000385
hbos6b470a92016-04-28 05:14:21 -0700386 EXPECT_TRUE(*identity_rsa2_ == *identity_rsa2_);
387 EXPECT_FALSE(*identity_rsa2_ == *identity_ecdsa1_);
388 EXPECT_FALSE(*identity_rsa2_ == *identity_ecdsa2_);
389
390 EXPECT_TRUE(*identity_ecdsa1_ == *identity_ecdsa1_);
391 EXPECT_FALSE(*identity_ecdsa1_ == *identity_ecdsa2_);
392}
393
394TEST_F(SSLIdentityTest, FromPEMStringsRSA) {
jbauch555604a2016-04-26 03:13:22 -0700395 std::unique_ptr<SSLIdentity> identity(
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100396 SSLIdentity::CreateFromPEMStrings(kRSA_PRIVATE_KEY_PEM, kRSA_CERT_PEM));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000397 EXPECT_TRUE(identity);
hbos6b470a92016-04-28 05:14:21 -0700398 EXPECT_EQ(kRSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
399 EXPECT_EQ(kRSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
hbose29352b2016-08-25 03:52:38 -0700400 EXPECT_EQ(kRSA_CERT_PEM, identity->certificate().ToPEMString());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000401}
402
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200403TEST_F(SSLIdentityTest, FromPEMStringsEC) {
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100404 std::unique_ptr<SSLIdentity> identity(SSLIdentity::CreateFromPEMStrings(
405 kECDSA_PRIVATE_KEY_PEM, kECDSA_CERT_PEM));
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200406 EXPECT_TRUE(identity);
hbos6b470a92016-04-28 05:14:21 -0700407 EXPECT_EQ(kECDSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
408 EXPECT_EQ(kECDSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
hbose29352b2016-08-25 03:52:38 -0700409 EXPECT_EQ(kECDSA_CERT_PEM, identity->certificate().ToPEMString());
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200410}
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200411
Taylor Brandstetter165c6182020-12-10 16:23:03 -0800412TEST_F(SSLIdentityTest, FromPEMChainStrings) {
413 // This doesn't form a valid certificate chain, but that doesn't matter for
414 // the purposes of the test
415 std::string chain(kRSA_CERT_PEM);
416 chain.append(kTestCertificate);
417 std::unique_ptr<SSLIdentity> identity(
418 SSLIdentity::CreateFromPEMChainStrings(kRSA_PRIVATE_KEY_PEM, chain));
419 EXPECT_TRUE(identity);
420 EXPECT_EQ(kRSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
421 EXPECT_EQ(kRSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
422 ASSERT_EQ(2u, identity->cert_chain().GetSize());
423 EXPECT_EQ(kRSA_CERT_PEM, identity->cert_chain().Get(0).ToPEMString());
424 EXPECT_EQ(kTestCertificate, identity->cert_chain().Get(1).ToPEMString());
425}
426
hbos6b470a92016-04-28 05:14:21 -0700427TEST_F(SSLIdentityTest, CloneIdentityRSA) {
428 TestCloningIdentity(*identity_rsa1_);
429 TestCloningIdentity(*identity_rsa2_);
430}
431
432TEST_F(SSLIdentityTest, CloneIdentityECDSA) {
433 TestCloningIdentity(*identity_ecdsa1_);
434 TestCloningIdentity(*identity_ecdsa2_);
435}
436
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000437TEST_F(SSLIdentityTest, PemDerConversion) {
438 std::string der;
439 EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der));
440
Yves Gerey665174f2018-06-19 15:03:05 +0200441 EXPECT_EQ(
442 kTestCertificate,
443 SSLIdentity::DerToPem("CERTIFICATE",
444 reinterpret_cast<const unsigned char*>(der.data()),
445 der.length()));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000446}
447
448TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) {
449 TestGetSignatureDigestAlgorithm();
450}
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100451
hbose29352b2016-08-25 03:52:38 -0700452TEST_F(SSLIdentityTest, SSLCertificateGetStatsRSA) {
453 std::unique_ptr<SSLIdentity> identity(
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100454 SSLIdentity::CreateFromPEMStrings(kRSA_PRIVATE_KEY_PEM, kRSA_CERT_PEM));
hbose29352b2016-08-25 03:52:38 -0700455 std::unique_ptr<rtc::SSLCertificateStats> stats =
456 identity->certificate().GetStats();
457 EXPECT_EQ(stats->fingerprint, kRSA_FINGERPRINT);
458 EXPECT_EQ(stats->fingerprint_algorithm, kRSA_FINGERPRINT_ALGORITHM);
459 EXPECT_EQ(stats->base64_certificate, kRSA_BASE64_CERTIFICATE);
460 EXPECT_FALSE(stats->issuer);
461}
462
463TEST_F(SSLIdentityTest, SSLCertificateGetStatsECDSA) {
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100464 std::unique_ptr<SSLIdentity> identity(SSLIdentity::CreateFromPEMStrings(
465 kECDSA_PRIVATE_KEY_PEM, kECDSA_CERT_PEM));
hbose29352b2016-08-25 03:52:38 -0700466 std::unique_ptr<rtc::SSLCertificateStats> stats =
467 identity->certificate().GetStats();
468 EXPECT_EQ(stats->fingerprint, kECDSA_FINGERPRINT);
469 EXPECT_EQ(stats->fingerprint_algorithm, kECDSA_FINGERPRINT_ALGORITHM);
470 EXPECT_EQ(stats->base64_certificate, kECDSA_BASE64_CERTIFICATE);
471 EXPECT_FALSE(stats->issuer);
472}
473
474TEST_F(SSLIdentityTest, SSLCertificateGetStatsWithChain) {
475 std::vector<std::string> ders;
476 ders.push_back("every der results in");
477 ders.push_back("an identity + certificate");
478 ders.push_back("in a certificate chain");
479 IdentityAndInfo info = CreateFakeIdentityAndInfoFromDers(ders);
480 EXPECT_TRUE(info.identity);
481 EXPECT_EQ(info.ders, ders);
482 EXPECT_EQ(info.pems.size(), info.ders.size());
483 EXPECT_EQ(info.fingerprints.size(), info.ders.size());
484
485 std::unique_ptr<rtc::SSLCertificateStats> first_stats =
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800486 info.identity->cert_chain().GetStats();
hbose29352b2016-08-25 03:52:38 -0700487 rtc::SSLCertificateStats* cert_stats = first_stats.get();
488 for (size_t i = 0; i < info.ders.size(); ++i) {
489 EXPECT_EQ(cert_stats->fingerprint, info.fingerprints[i]);
490 EXPECT_EQ(cert_stats->fingerprint_algorithm, "sha-1");
491 EXPECT_EQ(cert_stats->base64_certificate, info.pems[i]);
492 cert_stats = cert_stats->issuer.get();
493 EXPECT_EQ(static_cast<bool>(cert_stats), i + 1 < info.ders.size());
494 }
495}
496
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200497class SSLIdentityExpirationTest : public ::testing::Test {
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100498 public:
499 SSLIdentityExpirationTest() {
500 // Set use of the test RNG to get deterministic expiration timestamp.
501 rtc::SetRandomTestMode(true);
502 }
Steve Anton9de3aac2017-10-24 10:08:26 -0700503 ~SSLIdentityExpirationTest() override {
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100504 // Put it back for the next test.
505 rtc::SetRandomTestMode(false);
506 }
507
508 void TestASN1TimeToSec() {
509 struct asn_example {
510 const char* string;
511 bool long_format;
512 int64_t want;
513 } static const data[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200514 // clang-format off
515 // clang formatting breaks this nice alignment
516
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100517 // Valid examples.
518 {"19700101000000Z", true, 0},
519 {"700101000000Z", false, 0},
520 {"19700101000001Z", true, 1},
521 {"700101000001Z", false, 1},
522 {"19700101000100Z", true, 60},
523 {"19700101000101Z", true, 61},
524 {"19700101010000Z", true, 3600},
525 {"19700101010001Z", true, 3601},
526 {"19700101010100Z", true, 3660},
527 {"19700101010101Z", true, 3661},
528 {"710911012345Z", false, 53400225},
529 {"20000101000000Z", true, 946684800},
530 {"20000101000000Z", true, 946684800},
531 {"20151130140156Z", true, 1448892116},
532 {"151130140156Z", false, 1448892116},
533 {"20491231235959Z", true, 2524607999},
534 {"491231235959Z", false, 2524607999},
535 {"20500101000000Z", true, 2524607999+1},
536 {"20700101000000Z", true, 3155760000},
537 {"21000101000000Z", true, 4102444800},
538 {"24000101000000Z", true, 13569465600},
539
540 // Invalid examples.
541 {"19700101000000", true, -1}, // missing Z long format
542 {"19700101000000X", true, -1}, // X instead of Z long format
543 {"197001010000000", true, -1}, // 0 instead of Z long format
544 {"1970010100000000Z", true, -1}, // excess digits long format
545 {"700101000000", false, -1}, // missing Z short format
546 {"700101000000X", false, -1}, // X instead of Z short format
547 {"7001010000000", false, -1}, // 0 instead of Z short format
548 {"70010100000000Z", false, -1}, // excess digits short format
549 {":9700101000000Z", true, -1}, // invalid character
550 {"1:700101000001Z", true, -1}, // invalid character
551 {"19:00101000100Z", true, -1}, // invalid character
552 {"197:0101000101Z", true, -1}, // invalid character
553 {"1970:101010000Z", true, -1}, // invalid character
554 {"19700:01010001Z", true, -1}, // invalid character
555 {"197001:1010100Z", true, -1}, // invalid character
556 {"1970010:010101Z", true, -1}, // invalid character
557 {"70010100:000Z", false, -1}, // invalid character
558 {"700101000:01Z", false, -1}, // invalid character
559 {"2000010100:000Z", true, -1}, // invalid character
560 {"21000101000:00Z", true, -1}, // invalid character
561 {"240001010000:0Z", true, -1}, // invalid character
562 {"500101000000Z", false, -1}, // but too old for epoch
563 {"691231235959Z", false, -1}, // too old for epoch
564 {"19611118043000Z", false, -1}, // way too old for epoch
Yves Gerey665174f2018-06-19 15:03:05 +0200565
566 // clang-format off
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100567 };
568
569 unsigned char buf[20];
570
571 // Run all examples and check for the expected result.
572 for (const auto& entry : data) {
573 size_t length = strlen(entry.string);
574 memcpy(buf, entry.string, length); // Copy the ASN1 string...
575 buf[length] = rtc::CreateRandomId(); // ...and terminate it with junk.
576 int64_t res = rtc::ASN1TimeToSec(buf, length, entry.long_format);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100577 RTC_LOG(LS_VERBOSE) << entry.string;
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100578 ASSERT_EQ(entry.want, res);
579 }
580 // Run all examples again, but with an invalid length.
581 for (const auto& entry : data) {
582 size_t length = strlen(entry.string);
583 memcpy(buf, entry.string, length); // Copy the ASN1 string...
584 buf[length] = rtc::CreateRandomId(); // ...and terminate it with junk.
585 int64_t res = rtc::ASN1TimeToSec(buf, length - 1, entry.long_format);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100586 RTC_LOG(LS_VERBOSE) << entry.string;
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100587 ASSERT_EQ(-1, res);
588 }
589 }
590
591 void TestExpireTime(int times) {
torbjornge8dc0812016-02-15 09:35:54 -0800592 // We test just ECDSA here since what we're out to exercise is the
593 // interfaces for expiration setting and reading.
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100594 for (int i = 0; i < times; i++) {
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100595 // We limit the time to < 2^31 here, i.e., we stay before 2038, since else
596 // we hit time offset limitations in OpenSSL on some 32-bit systems.
Taylor Brandstetter88dec832016-03-15 09:57:55 -0700597 time_t time_before_generation = time(nullptr);
598 time_t lifetime =
599 rtc::CreateRandomId() % (0x80000000 - time_before_generation);
torbjornge8dc0812016-02-15 09:35:54 -0800600 rtc::KeyParams key_params = rtc::KeyParams::ECDSA(rtc::EC_NIST_P256);
Harald Alvestrand8515d5a2020-03-20 22:51:32 +0100601 auto identity =
602 rtc::SSLIdentity::Create("", key_params, lifetime);
Taylor Brandstetter88dec832016-03-15 09:57:55 -0700603 time_t time_after_generation = time(nullptr);
604 EXPECT_LE(time_before_generation + lifetime,
605 identity->certificate().CertificateExpirationTime());
606 EXPECT_GE(time_after_generation + lifetime,
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100607 identity->certificate().CertificateExpirationTime());
Torbjorn Granlund46c9cc02015-12-01 13:06:34 +0100608 }
609 }
610};
611
612TEST_F(SSLIdentityExpirationTest, TestASN1TimeToSec) {
613 TestASN1TimeToSec();
614}
615
616TEST_F(SSLIdentityExpirationTest, TestExpireTime) {
617 TestExpireTime(500);
618}