Home | History | Annotate | Download | only in base
      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:
     34   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 
     47   uint64_t NowSeconds() const {
     48     return TimeNanos() / kNumNanosecsPerSec;
     49   }
     50 
     51   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 
     59   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.
     68   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 
     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 
    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 
    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