xref: /aosp_15_r20/external/webrtc/rtc_base/rtc_certificate_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <time.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_identity.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker namespace rtc {
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace {
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker static const char* kTestCertCommonName = "RTCCertificateTest's certificate";
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker }  // namespace
31*d9f75844SAndroid Build Coastguard Worker 
32*d9f75844SAndroid Build Coastguard Worker class RTCCertificateTest : public ::testing::Test {
33*d9f75844SAndroid Build Coastguard Worker  protected:
GenerateECDSA()34*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> GenerateECDSA() {
35*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<SSLIdentity> identity(
36*d9f75844SAndroid Build Coastguard Worker         SSLIdentity::Create(kTestCertCommonName, KeyParams::ECDSA()));
37*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(identity);
38*d9f75844SAndroid Build Coastguard Worker     return RTCCertificate::Create(std::move(identity));
39*d9f75844SAndroid Build Coastguard Worker   }
40*d9f75844SAndroid Build Coastguard Worker 
41*d9f75844SAndroid Build Coastguard Worker   // Timestamp note:
42*d9f75844SAndroid Build Coastguard Worker   //   All timestamps in this unittest are expressed in number of seconds since
43*d9f75844SAndroid Build Coastguard Worker   // epoch, 1970-01-01T00:00:00Z (UTC). The RTCCertificate interface uses ms,
44*d9f75844SAndroid Build Coastguard Worker   // but only seconds-precision is supported by SSLCertificate. To make the
45*d9f75844SAndroid Build Coastguard Worker   // tests clearer we convert everything to seconds since the precision matters
46*d9f75844SAndroid Build Coastguard Worker   // when generating certificates or comparing timestamps.
47*d9f75844SAndroid Build Coastguard Worker   //   As a result, ExpiresSeconds and HasExpiredSeconds are used instead of
48*d9f75844SAndroid Build Coastguard Worker   // RTCCertificate::Expires and ::HasExpired for ms -> s conversion.
49*d9f75844SAndroid Build Coastguard Worker 
NowSeconds() const50*d9f75844SAndroid Build Coastguard Worker   uint64_t NowSeconds() const { return TimeNanos() / kNumNanosecsPerSec; }
51*d9f75844SAndroid Build Coastguard Worker 
ExpiresSeconds(const scoped_refptr<RTCCertificate> & cert) const52*d9f75844SAndroid Build Coastguard Worker   uint64_t ExpiresSeconds(const scoped_refptr<RTCCertificate>& cert) const {
53*d9f75844SAndroid Build Coastguard Worker     uint64_t exp_ms = cert->Expires();
54*d9f75844SAndroid Build Coastguard Worker     uint64_t exp_s = exp_ms / kNumMillisecsPerSec;
55*d9f75844SAndroid Build Coastguard Worker     // Make sure this did not result in loss of precision.
56*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK_EQ(exp_s * kNumMillisecsPerSec, exp_ms);
57*d9f75844SAndroid Build Coastguard Worker     return exp_s;
58*d9f75844SAndroid Build Coastguard Worker   }
59*d9f75844SAndroid Build Coastguard Worker 
HasExpiredSeconds(const scoped_refptr<RTCCertificate> & cert,uint64_t now_s) const60*d9f75844SAndroid Build Coastguard Worker   bool HasExpiredSeconds(const scoped_refptr<RTCCertificate>& cert,
61*d9f75844SAndroid Build Coastguard Worker                          uint64_t now_s) const {
62*d9f75844SAndroid Build Coastguard Worker     return cert->HasExpired(now_s * kNumMillisecsPerSec);
63*d9f75844SAndroid Build Coastguard Worker   }
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker   // An RTC_CHECK ensures that `expires_s` this is in valid range of time_t as
66*d9f75844SAndroid Build Coastguard Worker   // is required by SSLIdentityParams. On some 32-bit systems time_t is limited
67*d9f75844SAndroid Build Coastguard Worker   // to < 2^31. On such systems this will fail for expiration times of year 2038
68*d9f75844SAndroid Build Coastguard Worker   // or later.
GenerateCertificateWithExpires(uint64_t expires_s) const69*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> GenerateCertificateWithExpires(
70*d9f75844SAndroid Build Coastguard Worker       uint64_t expires_s) const {
71*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(IsValueInRangeForNumericType<time_t>(expires_s));
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker     SSLIdentityParams params;
74*d9f75844SAndroid Build Coastguard Worker     params.common_name = kTestCertCommonName;
75*d9f75844SAndroid Build Coastguard Worker     params.not_before = 0;
76*d9f75844SAndroid Build Coastguard Worker     params.not_after = static_cast<time_t>(expires_s);
77*d9f75844SAndroid Build Coastguard Worker     // Certificate type does not matter for our purposes, using ECDSA because it
78*d9f75844SAndroid Build Coastguard Worker     // is fast to generate.
79*d9f75844SAndroid Build Coastguard Worker     params.key_params = KeyParams::ECDSA();
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<SSLIdentity> identity(SSLIdentity::CreateForTest(params));
82*d9f75844SAndroid Build Coastguard Worker     return RTCCertificate::Create(std::move(identity));
83*d9f75844SAndroid Build Coastguard Worker   }
84*d9f75844SAndroid Build Coastguard Worker };
85*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,NewCertificateNotExpired)86*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, NewCertificateNotExpired) {
87*d9f75844SAndroid Build Coastguard Worker   // Generate a real certificate without specifying the expiration time.
88*d9f75844SAndroid Build Coastguard Worker   // Certificate type doesn't matter, using ECDSA because it's fast to generate.
89*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> certificate = GenerateECDSA();
90*d9f75844SAndroid Build Coastguard Worker 
91*d9f75844SAndroid Build Coastguard Worker   uint64_t now = NowSeconds();
92*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasExpiredSeconds(certificate, now));
93*d9f75844SAndroid Build Coastguard Worker   // Even without specifying the expiration time we would expect it to be valid
94*d9f75844SAndroid Build Coastguard Worker   // for at least half an hour.
95*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasExpiredSeconds(certificate, now + 30 * 60));
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,UsesExpiresAskedFor)98*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, UsesExpiresAskedFor) {
99*d9f75844SAndroid Build Coastguard Worker   uint64_t now = NowSeconds();
100*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> certificate =
101*d9f75844SAndroid Build Coastguard Worker       GenerateCertificateWithExpires(now);
102*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(now, ExpiresSeconds(certificate));
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,ExpiresInOneSecond)105*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, ExpiresInOneSecond) {
106*d9f75844SAndroid Build Coastguard Worker   // Generate a certificate that expires in 1s.
107*d9f75844SAndroid Build Coastguard Worker   uint64_t now = NowSeconds();
108*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> certificate =
109*d9f75844SAndroid Build Coastguard Worker       GenerateCertificateWithExpires(now + 1);
110*d9f75844SAndroid Build Coastguard Worker   // Now it should not have expired.
111*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(HasExpiredSeconds(certificate, now));
112*d9f75844SAndroid Build Coastguard Worker   // In 2s it should have expired.
113*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(HasExpiredSeconds(certificate, now + 2));
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,DifferentCertificatesNotEqual)116*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, DifferentCertificatesNotEqual) {
117*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> a = GenerateECDSA();
118*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> b = GenerateECDSA();
119*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(*a != *b);
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,CloneWithPEMSerialization)122*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, CloneWithPEMSerialization) {
123*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> orig = GenerateECDSA();
124*d9f75844SAndroid Build Coastguard Worker 
125*d9f75844SAndroid Build Coastguard Worker   // To PEM.
126*d9f75844SAndroid Build Coastguard Worker   RTCCertificatePEM orig_pem = orig->ToPEM();
127*d9f75844SAndroid Build Coastguard Worker   // Clone from PEM.
128*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> clone = RTCCertificate::FromPEM(orig_pem);
129*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(clone);
130*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(*orig == *clone);
131*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(orig->Expires(), clone->Expires());
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker 
TEST_F(RTCCertificateTest,FromPEMWithInvalidPEM)134*d9f75844SAndroid Build Coastguard Worker TEST_F(RTCCertificateTest, FromPEMWithInvalidPEM) {
135*d9f75844SAndroid Build Coastguard Worker   RTCCertificatePEM pem("not a valid PEM", "not a valid PEM");
136*d9f75844SAndroid Build Coastguard Worker   scoped_refptr<RTCCertificate> certificate = RTCCertificate::FromPEM(pem);
137*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(certificate);
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker 
140*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
141