• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2016 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 "rtc_base/rtc_certificate_generator.h"
12 
13 #include <memory>
14 
15 #include "absl/types/optional.h"
16 #include "rtc_base/checks.h"
17 #include "rtc_base/gunit.h"
18 #include "rtc_base/ref_counted_object.h"
19 #include "rtc_base/thread.h"
20 #include "test/gtest.h"
21 
22 namespace rtc {
23 
24 class RTCCertificateGeneratorFixture : public RTCCertificateGeneratorCallback {
25  public:
RTCCertificateGeneratorFixture()26   RTCCertificateGeneratorFixture()
27       : signaling_thread_(Thread::Current()),
28         worker_thread_(Thread::Create()),
29         generate_async_completed_(false) {
30     RTC_CHECK(signaling_thread_);
31     RTC_CHECK(worker_thread_->Start());
32     generator_.reset(
33         new RTCCertificateGenerator(signaling_thread_, worker_thread_.get()));
34   }
~RTCCertificateGeneratorFixture()35   ~RTCCertificateGeneratorFixture() override {}
36 
generator() const37   RTCCertificateGenerator* generator() const { return generator_.get(); }
certificate() const38   RTCCertificate* certificate() const { return certificate_.get(); }
39 
OnSuccess(const scoped_refptr<RTCCertificate> & certificate)40   void OnSuccess(const scoped_refptr<RTCCertificate>& certificate) override {
41     RTC_CHECK(signaling_thread_->IsCurrent());
42     RTC_CHECK(certificate);
43     certificate_ = certificate;
44     generate_async_completed_ = true;
45   }
OnFailure()46   void OnFailure() override {
47     RTC_CHECK(signaling_thread_->IsCurrent());
48     certificate_ = nullptr;
49     generate_async_completed_ = true;
50   }
51 
GenerateAsyncCompleted()52   bool GenerateAsyncCompleted() {
53     RTC_CHECK(signaling_thread_->IsCurrent());
54     if (generate_async_completed_) {
55       // Reset flag so that future generation requests are not considered done.
56       generate_async_completed_ = false;
57       return true;
58     }
59     return false;
60   }
61 
62  protected:
63   Thread* const signaling_thread_;
64   std::unique_ptr<Thread> worker_thread_;
65   std::unique_ptr<RTCCertificateGenerator> generator_;
66   scoped_refptr<RTCCertificate> certificate_;
67   bool generate_async_completed_;
68 };
69 
70 class RTCCertificateGeneratorTest : public ::testing::Test {
71  public:
RTCCertificateGeneratorTest()72   RTCCertificateGeneratorTest()
73       : fixture_(new RefCountedObject<RTCCertificateGeneratorFixture>()) {}
74 
75  protected:
76   static constexpr int kGenerationTimeoutMs = 10000;
77 
78   scoped_refptr<RTCCertificateGeneratorFixture> fixture_;
79 };
80 
TEST_F(RTCCertificateGeneratorTest,GenerateECDSA)81 TEST_F(RTCCertificateGeneratorTest, GenerateECDSA) {
82   EXPECT_TRUE(RTCCertificateGenerator::GenerateCertificate(KeyParams::ECDSA(),
83                                                            absl::nullopt));
84 }
85 
TEST_F(RTCCertificateGeneratorTest,GenerateRSA)86 TEST_F(RTCCertificateGeneratorTest, GenerateRSA) {
87   EXPECT_TRUE(RTCCertificateGenerator::GenerateCertificate(KeyParams::RSA(),
88                                                            absl::nullopt));
89 }
90 
TEST_F(RTCCertificateGeneratorTest,GenerateAsyncECDSA)91 TEST_F(RTCCertificateGeneratorTest, GenerateAsyncECDSA) {
92   EXPECT_FALSE(fixture_->certificate());
93   fixture_->generator()->GenerateCertificateAsync(KeyParams::ECDSA(),
94                                                   absl::nullopt, fixture_);
95   // Until generation has completed, the certificate is null. Since this is an
96   // async call, generation must not have completed until we process messages
97   // posted to this thread (which is done by |EXPECT_TRUE_WAIT|).
98   EXPECT_FALSE(fixture_->GenerateAsyncCompleted());
99   EXPECT_FALSE(fixture_->certificate());
100   EXPECT_TRUE_WAIT(fixture_->GenerateAsyncCompleted(), kGenerationTimeoutMs);
101   EXPECT_TRUE(fixture_->certificate());
102 }
103 
TEST_F(RTCCertificateGeneratorTest,GenerateWithExpires)104 TEST_F(RTCCertificateGeneratorTest, GenerateWithExpires) {
105   // By generating two certificates with different expiration we can compare the
106   // two expiration times relative to each other without knowing the current
107   // time relative to epoch, 1970-01-01T00:00:00Z. This verifies that the
108   // expiration parameter is correctly used relative to the generator's clock,
109   // but does not verify that this clock is relative to epoch.
110 
111   // Generate a certificate that expires immediately.
112   scoped_refptr<RTCCertificate> cert_a =
113       RTCCertificateGenerator::GenerateCertificate(KeyParams::ECDSA(), 0);
114   EXPECT_TRUE(cert_a);
115 
116   // Generate a certificate that expires in one minute.
117   const uint64_t kExpiresMs = 60000;
118   scoped_refptr<RTCCertificate> cert_b =
119       RTCCertificateGenerator::GenerateCertificate(KeyParams::ECDSA(),
120                                                    kExpiresMs);
121   EXPECT_TRUE(cert_b);
122 
123   // Verify that |cert_b| expires approximately |kExpiresMs| after |cert_a|
124   // (allowing a +/- 1 second plus maximum generation time difference).
125   EXPECT_GT(cert_b->Expires(), cert_a->Expires());
126   uint64_t expires_diff = cert_b->Expires() - cert_a->Expires();
127   EXPECT_GE(expires_diff, kExpiresMs);
128   EXPECT_LE(expires_diff, kExpiresMs + 2 * kGenerationTimeoutMs + 1000);
129 }
130 
TEST_F(RTCCertificateGeneratorTest,GenerateWithInvalidParamsShouldFail)131 TEST_F(RTCCertificateGeneratorTest, GenerateWithInvalidParamsShouldFail) {
132   KeyParams invalid_params = KeyParams::RSA(0, 0);
133   EXPECT_FALSE(invalid_params.IsValid());
134 
135   EXPECT_FALSE(RTCCertificateGenerator::GenerateCertificate(invalid_params,
136                                                             absl::nullopt));
137 
138   fixture_->generator()->GenerateCertificateAsync(invalid_params, absl::nullopt,
139                                                   fixture_);
140   EXPECT_TRUE_WAIT(fixture_->GenerateAsyncCompleted(), kGenerationTimeoutMs);
141   EXPECT_FALSE(fixture_->certificate());
142 }
143 
144 }  // namespace rtc
145