1 /*
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
11 #include <utility>
12
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/fakesslidentity.h"
15 #include "webrtc/base/gunit.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/base/rtccertificate.h"
18 #include "webrtc/base/safe_conversions.h"
19 #include "webrtc/base/scoped_ptr.h"
20 #include "webrtc/base/sslidentity.h"
21 #include "webrtc/base/thread.h"
22 #include "webrtc/base/timeutils.h"
23
24 namespace rtc {
25
26 namespace {
27
28 static const char* kTestCertCommonName = "RTCCertificateTest's certificate";
29
30 } // namespace
31
32 class RTCCertificateTest : public testing::Test {
33 public:
RTCCertificateTest()34 RTCCertificateTest() {}
~RTCCertificateTest()35 ~RTCCertificateTest() {}
36
37 protected:
38 // Timestamp note:
39 // All timestamps in this unittest are expressed in number of seconds since
40 // epoch, 1970-01-01T00:00:00Z (UTC). The RTCCertificate interface uses ms,
41 // but only seconds-precision is supported by SSLCertificate. To make the
42 // tests clearer we convert everything to seconds since the precision matters
43 // when generating certificates or comparing timestamps.
44 // As a result, ExpiresSeconds and HasExpiredSeconds are used instead of
45 // RTCCertificate::Expires and ::HasExpired for ms -> s conversion.
46
NowSeconds() const47 uint64_t NowSeconds() const {
48 return TimeNanos() / kNumNanosecsPerSec;
49 }
50
ExpiresSeconds(const scoped_refptr<RTCCertificate> & cert) const51 uint64_t ExpiresSeconds(const scoped_refptr<RTCCertificate>& cert) const {
52 uint64_t exp_ms = cert->Expires();
53 uint64_t exp_s = exp_ms / kNumMillisecsPerSec;
54 // Make sure this did not result in loss of precision.
55 RTC_CHECK_EQ(exp_s * kNumMillisecsPerSec, exp_ms);
56 return exp_s;
57 }
58
HasExpiredSeconds(const scoped_refptr<RTCCertificate> & cert,uint64_t now_s) const59 bool HasExpiredSeconds(const scoped_refptr<RTCCertificate>& cert,
60 uint64_t now_s) const {
61 return cert->HasExpired(now_s * kNumMillisecsPerSec);
62 }
63
64 // An RTC_CHECK ensures that |expires_s| this is in valid range of time_t as
65 // is required by SSLIdentityParams. On some 32-bit systems time_t is limited
66 // to < 2^31. On such systems this will fail for expiration times of year 2038
67 // or later.
GenerateCertificateWithExpires(uint64_t expires_s) const68 scoped_refptr<RTCCertificate> GenerateCertificateWithExpires(
69 uint64_t expires_s) const {
70 RTC_CHECK(IsValueInRangeForNumericType<time_t>(expires_s));
71
72 SSLIdentityParams params;
73 params.common_name = kTestCertCommonName;
74 params.not_before = 0;
75 params.not_after = static_cast<time_t>(expires_s);
76 // Certificate type does not matter for our purposes, using ECDSA because it
77 // is fast to generate.
78 params.key_params = KeyParams::ECDSA();
79
80 scoped_ptr<SSLIdentity> identity(SSLIdentity::GenerateForTest(params));
81 return RTCCertificate::Create(std::move(identity));
82 }
83 };
84
TEST_F(RTCCertificateTest,NewCertificateNotExpired)85 TEST_F(RTCCertificateTest, NewCertificateNotExpired) {
86 // Generate a real certificate without specifying the expiration time.
87 // Certificate type doesn't matter, using ECDSA because it's fast to generate.
88 scoped_ptr<SSLIdentity> identity(
89 SSLIdentity::Generate(kTestCertCommonName, KeyParams::ECDSA()));
90 scoped_refptr<RTCCertificate> certificate =
91 RTCCertificate::Create(std::move(identity));
92
93 uint64_t now = NowSeconds();
94 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
95 // Even without specifying the expiration time we would expect it to be valid
96 // for at least half an hour.
97 EXPECT_FALSE(HasExpiredSeconds(certificate, now + 30*60));
98 }
99
TEST_F(RTCCertificateTest,UsesExpiresAskedFor)100 TEST_F(RTCCertificateTest, UsesExpiresAskedFor) {
101 uint64_t now = NowSeconds();
102 scoped_refptr<RTCCertificate> certificate =
103 GenerateCertificateWithExpires(now);
104 EXPECT_EQ(now, ExpiresSeconds(certificate));
105 }
106
TEST_F(RTCCertificateTest,ExpiresInOneSecond)107 TEST_F(RTCCertificateTest, ExpiresInOneSecond) {
108 // Generate a certificate that expires in 1s.
109 uint64_t now = NowSeconds();
110 scoped_refptr<RTCCertificate> certificate =
111 GenerateCertificateWithExpires(now + 1);
112 // Now it should not have expired.
113 EXPECT_FALSE(HasExpiredSeconds(certificate, now));
114 // In 2s it should have expired.
115 EXPECT_TRUE(HasExpiredSeconds(certificate, now + 2));
116 }
117
118 } // namespace rtc
119