blob: f5a777c6497ed865132397b82dcf464dfac63fe2 [file] [log] [blame]
hbos3980d462015-12-09 05:26:49 -08001/*
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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <time.h>
jbauch555604a2016-04-26 03:13:22 -070012#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/checks.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010016#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/rtccertificate.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/sslidentity.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/timeutils.h"
Yves Gerey3e707812018-11-28 16:47:49 +010020#include "test/gtest.h"
hbos3980d462015-12-09 05:26:49 -080021
22namespace rtc {
23
24namespace {
25
26static const char* kTestCertCommonName = "RTCCertificateTest's certificate";
27
28} // namespace
29
30class RTCCertificateTest : public testing::Test {
hbos3980d462015-12-09 05:26:49 -080031 protected:
hbos6b470a92016-04-28 05:14:21 -070032 scoped_refptr<RTCCertificate> GenerateECDSA() {
33 std::unique_ptr<SSLIdentity> identity(
34 SSLIdentity::Generate(kTestCertCommonName, KeyParams::ECDSA()));
35 RTC_CHECK(identity);
36 return RTCCertificate::Create(std::move(identity));
37 }
38
hbos3980d462015-12-09 05:26:49 -080039 // Timestamp note:
40 // All timestamps in this unittest are expressed in number of seconds since
41 // epoch, 1970-01-01T00:00:00Z (UTC). The RTCCertificate interface uses ms,
42 // but only seconds-precision is supported by SSLCertificate. To make the
43 // tests clearer we convert everything to seconds since the precision matters
44 // when generating certificates or comparing timestamps.
45 // As a result, ExpiresSeconds and HasExpiredSeconds are used instead of
46 // RTCCertificate::Expires and ::HasExpired for ms -> s conversion.
47
Yves Gerey665174f2018-06-19 15:03:05 +020048 uint64_t NowSeconds() const { return TimeNanos() / kNumNanosecsPerSec; }
hbos3980d462015-12-09 05:26:49 -080049
50 uint64_t ExpiresSeconds(const scoped_refptr<RTCCertificate>& cert) const {
51 uint64_t exp_ms = cert->Expires();
52 uint64_t exp_s = exp_ms / kNumMillisecsPerSec;
53 // Make sure this did not result in loss of precision.
54 RTC_CHECK_EQ(exp_s * kNumMillisecsPerSec, exp_ms);
55 return exp_s;
56 }
57
58 bool HasExpiredSeconds(const scoped_refptr<RTCCertificate>& cert,
59 uint64_t now_s) const {
60 return cert->HasExpired(now_s * kNumMillisecsPerSec);
61 }
62
63 // An RTC_CHECK ensures that |expires_s| this is in valid range of time_t as
64 // is required by SSLIdentityParams. On some 32-bit systems time_t is limited
65 // to < 2^31. On such systems this will fail for expiration times of year 2038
66 // or later.
67 scoped_refptr<RTCCertificate> GenerateCertificateWithExpires(
68 uint64_t expires_s) const {
69 RTC_CHECK(IsValueInRangeForNumericType<time_t>(expires_s));
70
71 SSLIdentityParams params;
72 params.common_name = kTestCertCommonName;
73 params.not_before = 0;
74 params.not_after = static_cast<time_t>(expires_s);
75 // Certificate type does not matter for our purposes, using ECDSA because it
76 // is fast to generate.
77 params.key_params = KeyParams::ECDSA();
78
jbauch555604a2016-04-26 03:13:22 -070079 std::unique_ptr<SSLIdentity> identity(SSLIdentity::GenerateForTest(params));
kwiberg0eb15ed2015-12-17 03:04:15 -080080 return RTCCertificate::Create(std::move(identity));
hbos3980d462015-12-09 05:26:49 -080081 }
82};
83
84TEST_F(RTCCertificateTest, NewCertificateNotExpired) {
85 // Generate a real certificate without specifying the expiration time.
86 // Certificate type doesn't matter, using ECDSA because it's fast to generate.
hbos6b470a92016-04-28 05:14:21 -070087 scoped_refptr<RTCCertificate> certificate = GenerateECDSA();
hbos3980d462015-12-09 05:26:49 -080088
89 uint64_t now = NowSeconds();
90 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
91 // Even without specifying the expiration time we would expect it to be valid
92 // for at least half an hour.
Yves Gerey665174f2018-06-19 15:03:05 +020093 EXPECT_FALSE(HasExpiredSeconds(certificate, now + 30 * 60));
hbos3980d462015-12-09 05:26:49 -080094}
95
96TEST_F(RTCCertificateTest, UsesExpiresAskedFor) {
97 uint64_t now = NowSeconds();
98 scoped_refptr<RTCCertificate> certificate =
99 GenerateCertificateWithExpires(now);
100 EXPECT_EQ(now, ExpiresSeconds(certificate));
101}
102
103TEST_F(RTCCertificateTest, ExpiresInOneSecond) {
104 // Generate a certificate that expires in 1s.
105 uint64_t now = NowSeconds();
106 scoped_refptr<RTCCertificate> certificate =
107 GenerateCertificateWithExpires(now + 1);
108 // Now it should not have expired.
109 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
110 // In 2s it should have expired.
111 EXPECT_TRUE(HasExpiredSeconds(certificate, now + 2));
112}
113
hbos6b470a92016-04-28 05:14:21 -0700114TEST_F(RTCCertificateTest, DifferentCertificatesNotEqual) {
115 scoped_refptr<RTCCertificate> a = GenerateECDSA();
116 scoped_refptr<RTCCertificate> b = GenerateECDSA();
117 EXPECT_TRUE(*a != *b);
118}
119
120TEST_F(RTCCertificateTest, CloneWithPEMSerialization) {
121 scoped_refptr<RTCCertificate> orig = GenerateECDSA();
122
123 // To PEM.
124 RTCCertificatePEM orig_pem = orig->ToPEM();
125 // Clone from PEM.
126 scoped_refptr<RTCCertificate> clone = RTCCertificate::FromPEM(orig_pem);
127 EXPECT_TRUE(clone);
128 EXPECT_TRUE(*orig == *clone);
129 EXPECT_EQ(orig->Expires(), clone->Expires());
130}
131
jbromanb9eaeba2016-10-20 10:27:21 -0700132TEST_F(RTCCertificateTest, FromPEMWithInvalidPEM) {
133 RTCCertificatePEM pem("not a valid PEM", "not a valid PEM");
134 scoped_refptr<RTCCertificate> certificate = RTCCertificate::FromPEM(pem);
135 EXPECT_FALSE(certificate);
136}
137
hbos3980d462015-12-09 05:26:49 -0800138} // namespace rtc