| OLD | NEW |
| (Empty) |
| 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 "webrtc/base/rtccertificategenerator.h" | |
| 12 | |
| 13 #include <algorithm> | |
| 14 #include <memory> | |
| 15 | |
| 16 #include "webrtc/base/checks.h" | |
| 17 #include "webrtc/base/sslidentity.h" | |
| 18 | |
| 19 namespace rtc { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 // A certificates' subject and issuer name. | |
| 24 const char kIdentityName[] = "WebRTC"; | |
| 25 | |
| 26 uint64_t kYearInSeconds = 365 * 24 * 60 * 60; | |
| 27 | |
| 28 enum { | |
| 29 MSG_GENERATE, | |
| 30 MSG_GENERATE_DONE, | |
| 31 }; | |
| 32 | |
| 33 // Helper class for generating certificates asynchronously; a single task | |
| 34 // instance is responsible for a single asynchronous certificate generation | |
| 35 // request. We are using a separate helper class so that a generation request | |
| 36 // can outlive the |RTCCertificateGenerator| that spawned it. | |
| 37 class RTCCertificateGenerationTask : public RefCountInterface, | |
| 38 public MessageHandler { | |
| 39 public: | |
| 40 RTCCertificateGenerationTask( | |
| 41 Thread* signaling_thread, | |
| 42 Thread* worker_thread, | |
| 43 const KeyParams& key_params, | |
| 44 const Optional<uint64_t>& expires_ms, | |
| 45 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) | |
| 46 : signaling_thread_(signaling_thread), | |
| 47 worker_thread_(worker_thread), | |
| 48 key_params_(key_params), | |
| 49 expires_ms_(expires_ms), | |
| 50 callback_(callback) { | |
| 51 RTC_DCHECK(signaling_thread_); | |
| 52 RTC_DCHECK(worker_thread_); | |
| 53 RTC_DCHECK(callback_); | |
| 54 } | |
| 55 ~RTCCertificateGenerationTask() override {} | |
| 56 | |
| 57 // Handles |MSG_GENERATE| and its follow-up |MSG_GENERATE_DONE|. | |
| 58 void OnMessage(Message* msg) override { | |
| 59 switch (msg->message_id) { | |
| 60 case MSG_GENERATE: | |
| 61 RTC_DCHECK(worker_thread_->IsCurrent()); | |
| 62 | |
| 63 // Perform the certificate generation work here on the worker thread. | |
| 64 certificate_ = RTCCertificateGenerator::GenerateCertificate( | |
| 65 key_params_, expires_ms_); | |
| 66 | |
| 67 // Handle callbacks on signaling thread. Pass on the |msg->pdata| | |
| 68 // (which references |this| with ref counting) to that thread. | |
| 69 signaling_thread_->Post(RTC_FROM_HERE, this, MSG_GENERATE_DONE, | |
| 70 msg->pdata); | |
| 71 break; | |
| 72 case MSG_GENERATE_DONE: | |
| 73 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 74 | |
| 75 // Perform callback with result here on the signaling thread. | |
| 76 if (certificate_) { | |
| 77 callback_->OnSuccess(certificate_); | |
| 78 } else { | |
| 79 callback_->OnFailure(); | |
| 80 } | |
| 81 | |
| 82 // Destroy |msg->pdata| which references |this| with ref counting. This | |
| 83 // may result in |this| being deleted - do not touch member variables | |
| 84 // after this line. | |
| 85 delete msg->pdata; | |
| 86 return; | |
| 87 default: | |
| 88 RTC_NOTREACHED(); | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 private: | |
| 93 Thread* const signaling_thread_; | |
| 94 Thread* const worker_thread_; | |
| 95 const KeyParams key_params_; | |
| 96 const Optional<uint64_t> expires_ms_; | |
| 97 const scoped_refptr<RTCCertificateGeneratorCallback> callback_; | |
| 98 scoped_refptr<RTCCertificate> certificate_; | |
| 99 }; | |
| 100 | |
| 101 } // namespace | |
| 102 | |
| 103 // static | |
| 104 scoped_refptr<RTCCertificate> | |
| 105 RTCCertificateGenerator::GenerateCertificate( | |
| 106 const KeyParams& key_params, | |
| 107 const Optional<uint64_t>& expires_ms) { | |
| 108 if (!key_params.IsValid()) | |
| 109 return nullptr; | |
| 110 SSLIdentity* identity; | |
| 111 if (!expires_ms) { | |
| 112 identity = SSLIdentity::Generate(kIdentityName, key_params); | |
| 113 } else { | |
| 114 uint64_t expires_s = *expires_ms / 1000; | |
| 115 // Limit the expiration time to something reasonable (a year). This was | |
| 116 // somewhat arbitrarily chosen. It also ensures that the value is not too | |
| 117 // large for the unspecified |time_t|. | |
| 118 expires_s = std::min(expires_s, kYearInSeconds); | |
| 119 // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe | |
| 120 // to assume it can hold up to a year's worth of seconds (and more), but | |
| 121 // |SSLIdentity::Generate| should stop relying on |time_t|. | |
| 122 // See bugs.webrtc.org/5720. | |
| 123 time_t cert_lifetime_s = static_cast<time_t>(expires_s); | |
| 124 identity = SSLIdentity::GenerateWithExpiration( | |
| 125 kIdentityName, key_params, cert_lifetime_s); | |
| 126 } | |
| 127 if (!identity) | |
| 128 return nullptr; | |
| 129 std::unique_ptr<SSLIdentity> identity_sptr(identity); | |
| 130 return RTCCertificate::Create(std::move(identity_sptr)); | |
| 131 } | |
| 132 | |
| 133 RTCCertificateGenerator::RTCCertificateGenerator( | |
| 134 Thread* signaling_thread, Thread* worker_thread) | |
| 135 : signaling_thread_(signaling_thread), | |
| 136 worker_thread_(worker_thread) { | |
| 137 RTC_DCHECK(signaling_thread_); | |
| 138 RTC_DCHECK(worker_thread_); | |
| 139 } | |
| 140 | |
| 141 void RTCCertificateGenerator::GenerateCertificateAsync( | |
| 142 const KeyParams& key_params, | |
| 143 const Optional<uint64_t>& expires_ms, | |
| 144 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) { | |
| 145 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
| 146 RTC_DCHECK(callback); | |
| 147 | |
| 148 // Create a new |RTCCertificateGenerationTask| for this generation request. It | |
| 149 // is reference counted and referenced by the message data, ensuring it lives | |
| 150 // until the task has completed (independent of |RTCCertificateGenerator|). | |
| 151 ScopedRefMessageData<RTCCertificateGenerationTask>* msg_data = | |
| 152 new ScopedRefMessageData<RTCCertificateGenerationTask>( | |
| 153 new RefCountedObject<RTCCertificateGenerationTask>( | |
| 154 signaling_thread_, worker_thread_, key_params, expires_ms, | |
| 155 callback)); | |
| 156 worker_thread_->Post(RTC_FROM_HERE, msg_data->data().get(), MSG_GENERATE, | |
| 157 msg_data); | |
| 158 } | |
| 159 | |
| 160 } // namespace rtc | |
| OLD | NEW |