blob: 63183883b35c4fb9b456669f6f1055e70e21fc11 [file] [log] [blame]
hbos3980d462015-12-09 13:26:491/*
2 * Copyright 2015 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
Jonas Olssona4d87372019-07-05 17:08:3311#include "rtc_base/rtc_certificate.h"
12
Yves Gerey3e707812018-11-28 15:47:4913#include <time.h>
Jonas Olssona4d87372019-07-05 17:08:3314
jbauch555604a2016-04-26 10:13:2215#include <memory>
kwiberg0eb15ed2015-12-17 11:04:1516#include <utility>
17
Mirko Bonadei92ea95e2017-09-15 04:47:3118#include "rtc_base/checks.h"
Karl Wiberge40468b2017-11-22 09:42:2619#include "rtc_base/numerics/safe_conversions.h"
Steve Anton10542f22019-01-11 17:11:0020#include "rtc_base/ssl_identity.h"
21#include "rtc_base/time_utils.h"
Yves Gerey3e707812018-11-28 15:47:4922#include "test/gtest.h"
hbos3980d462015-12-09 13:26:4923
24namespace rtc {
25
26namespace {
27
28static const char* kTestCertCommonName = "RTCCertificateTest's certificate";
29
30} // namespace
31
Mirko Bonadei6a489f22019-04-09 13:11:1232class RTCCertificateTest : public ::testing::Test {
hbos3980d462015-12-09 13:26:4933 protected:
hbos6b470a92016-04-28 12:14:2134 scoped_refptr<RTCCertificate> GenerateECDSA() {
35 std::unique_ptr<SSLIdentity> identity(
Harald Alvestrand8515d5a2020-03-20 21:51:3236 SSLIdentity::Create(kTestCertCommonName, KeyParams::ECDSA()));
hbos6b470a92016-04-28 12:14:2137 RTC_CHECK(identity);
38 return RTCCertificate::Create(std::move(identity));
39 }
40
hbos3980d462015-12-09 13:26:4941 // Timestamp note:
42 // All timestamps in this unittest are expressed in number of seconds since
43 // epoch, 1970-01-01T00:00:00Z (UTC). The RTCCertificate interface uses ms,
44 // but only seconds-precision is supported by SSLCertificate. To make the
45 // tests clearer we convert everything to seconds since the precision matters
46 // when generating certificates or comparing timestamps.
47 // As a result, ExpiresSeconds and HasExpiredSeconds are used instead of
48 // RTCCertificate::Expires and ::HasExpired for ms -> s conversion.
49
Yves Gerey665174f2018-06-19 13:03:0550 uint64_t NowSeconds() const { return TimeNanos() / kNumNanosecsPerSec; }
hbos3980d462015-12-09 13:26:4951
52 uint64_t ExpiresSeconds(const scoped_refptr<RTCCertificate>& cert) const {
53 uint64_t exp_ms = cert->Expires();
54 uint64_t exp_s = exp_ms / kNumMillisecsPerSec;
55 // Make sure this did not result in loss of precision.
56 RTC_CHECK_EQ(exp_s * kNumMillisecsPerSec, exp_ms);
57 return exp_s;
58 }
59
60 bool HasExpiredSeconds(const scoped_refptr<RTCCertificate>& cert,
61 uint64_t now_s) const {
62 return cert->HasExpired(now_s * kNumMillisecsPerSec);
63 }
64
Artem Titov96e3b992021-07-26 14:03:1465 // An RTC_CHECK ensures that `expires_s` this is in valid range of time_t as
hbos3980d462015-12-09 13:26:4966 // is required by SSLIdentityParams. On some 32-bit systems time_t is limited
67 // to < 2^31. On such systems this will fail for expiration times of year 2038
68 // or later.
69 scoped_refptr<RTCCertificate> GenerateCertificateWithExpires(
70 uint64_t expires_s) const {
71 RTC_CHECK(IsValueInRangeForNumericType<time_t>(expires_s));
72
73 SSLIdentityParams params;
74 params.common_name = kTestCertCommonName;
75 params.not_before = 0;
76 params.not_after = static_cast<time_t>(expires_s);
77 // Certificate type does not matter for our purposes, using ECDSA because it
78 // is fast to generate.
79 params.key_params = KeyParams::ECDSA();
80
Harald Alvestrand8515d5a2020-03-20 21:51:3281 std::unique_ptr<SSLIdentity> identity(SSLIdentity::CreateForTest(params));
kwiberg0eb15ed2015-12-17 11:04:1582 return RTCCertificate::Create(std::move(identity));
hbos3980d462015-12-09 13:26:4983 }
84};
85
86TEST_F(RTCCertificateTest, NewCertificateNotExpired) {
87 // Generate a real certificate without specifying the expiration time.
88 // Certificate type doesn't matter, using ECDSA because it's fast to generate.
hbos6b470a92016-04-28 12:14:2189 scoped_refptr<RTCCertificate> certificate = GenerateECDSA();
hbos3980d462015-12-09 13:26:4990
91 uint64_t now = NowSeconds();
92 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
93 // Even without specifying the expiration time we would expect it to be valid
94 // for at least half an hour.
Yves Gerey665174f2018-06-19 13:03:0595 EXPECT_FALSE(HasExpiredSeconds(certificate, now + 30 * 60));
hbos3980d462015-12-09 13:26:4996}
97
98TEST_F(RTCCertificateTest, UsesExpiresAskedFor) {
99 uint64_t now = NowSeconds();
100 scoped_refptr<RTCCertificate> certificate =
101 GenerateCertificateWithExpires(now);
102 EXPECT_EQ(now, ExpiresSeconds(certificate));
103}
104
105TEST_F(RTCCertificateTest, ExpiresInOneSecond) {
106 // Generate a certificate that expires in 1s.
107 uint64_t now = NowSeconds();
108 scoped_refptr<RTCCertificate> certificate =
109 GenerateCertificateWithExpires(now + 1);
110 // Now it should not have expired.
111 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
112 // In 2s it should have expired.
113 EXPECT_TRUE(HasExpiredSeconds(certificate, now + 2));
114}
115
hbos6b470a92016-04-28 12:14:21116TEST_F(RTCCertificateTest, DifferentCertificatesNotEqual) {
117 scoped_refptr<RTCCertificate> a = GenerateECDSA();
118 scoped_refptr<RTCCertificate> b = GenerateECDSA();
119 EXPECT_TRUE(*a != *b);
120}
121
122TEST_F(RTCCertificateTest, CloneWithPEMSerialization) {
123 scoped_refptr<RTCCertificate> orig = GenerateECDSA();
124
125 // To PEM.
126 RTCCertificatePEM orig_pem = orig->ToPEM();
127 // Clone from PEM.
128 scoped_refptr<RTCCertificate> clone = RTCCertificate::FromPEM(orig_pem);
129 EXPECT_TRUE(clone);
130 EXPECT_TRUE(*orig == *clone);
131 EXPECT_EQ(orig->Expires(), clone->Expires());
132}
133
jbromanb9eaeba2016-10-20 17:27:21134TEST_F(RTCCertificateTest, FromPEMWithInvalidPEM) {
135 RTCCertificatePEM pem("not a valid PEM", "not a valid PEM");
136 scoped_refptr<RTCCertificate> certificate = RTCCertificate::FromPEM(pem);
137 EXPECT_FALSE(certificate);
138}
139
hbos3980d462015-12-09 13:26:49140} // namespace rtc