| Index: content/browser/media/dtls_identity_store.cc
|
| diff --git a/content/browser/media/dtls_identity_store.cc b/content/browser/media/dtls_identity_store.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2948ddf873ba573b1bd7377eac0e9fd92740bd64
|
| --- /dev/null
|
| +++ b/content/browser/media/dtls_identity_store.cc
|
| @@ -0,0 +1,164 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/media/dtls_identity_store.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/callback_helpers.h"
|
| +#include "base/location.h"
|
| +#include "base/logging.h"
|
| +#include "base/rand_util.h"
|
| +#include "base/task_runner.h"
|
| +#include "base/threading/worker_pool.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "crypto/rsa_private_key.h"
|
| +#include "googleurl/src/gurl.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/cert/x509_certificate.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +struct DTLSIdentityRequestResult {
|
| + int error;
|
| + std::string certificate;
|
| + std::string private_key;
|
| +};
|
| +
|
| +static void GenerateIdentityWorker(const std::string& common_name,
|
| + DTLSIdentityRequestResult* result) {
|
| + result->error = net::OK;
|
| + std::string certificate;
|
| + std::vector<uint8> private_key_info;
|
| +
|
| + int serial_number = base::RandInt(0, std::numeric_limits<int>::max());
|
| +
|
| + scoped_ptr<crypto::RSAPrivateKey> key(crypto::RSAPrivateKey::Create(1024));
|
| + if (!key.get()) {
|
| + DLOG(ERROR) << "Unable to create key pair for client";
|
| + result->error = net::ERR_KEY_GENERATION_FAILED;
|
| + return;
|
| + }
|
| +
|
| + scoped_refptr<net::X509Certificate> cert =
|
| + net::X509Certificate::CreateSelfSigned(key.get(),
|
| + "CN=" + common_name,
|
| + serial_number,
|
| + base::TimeDelta::FromDays(30));
|
| + if (!cert) {
|
| + DLOG(ERROR) << "Unable to create x509 cert for client";
|
| + result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
|
| + return;
|
| + }
|
| + if (!net::X509Certificate::GetDEREncoded(cert->os_cert_handle(),
|
| + &result->certificate)) {
|
| + DLOG(ERROR) << "Unable to get the DER decoded data from the cert.";
|
| + result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
|
| + return;
|
| + }
|
| +
|
| + if (!key->ExportPrivateKey(&private_key_info)) {
|
| + DLOG(ERROR) << "Unable to export private key";
|
| + result->error = net::ERR_PRIVATE_KEY_EXPORT_FAILED;
|
| + return;
|
| + }
|
| +
|
| + result->private_key =
|
| + std::string(private_key_info.begin(), private_key_info.end());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class DTLSIdentityRequest {
|
| + public:
|
| + DTLSIdentityRequest(const DTLSIdentityStore::CompletionCallback& callback)
|
| + : callback_(callback) {}
|
| +
|
| + void Cancel() {
|
| + callback_.Reset();
|
| + }
|
| +
|
| + void Post(DTLSIdentityRequestResult* result) {
|
| + if (callback_.is_null())
|
| + return;
|
| + callback_.Run(result->error, result->certificate, result->private_key);
|
| + }
|
| +
|
| + private:
|
| + DTLSIdentityStore::CompletionCallback callback_;
|
| +};
|
| +
|
| +DTLSIdentityStore::RequestHandle::RequestHandle()
|
| + : store_(NULL),
|
| + request_(NULL) {}
|
| +
|
| +DTLSIdentityStore::RequestHandle::~RequestHandle() {
|
| + Cancel();
|
| +}
|
| +
|
| +void DTLSIdentityStore::RequestHandle::Cancel() {
|
| + if (request_) {
|
| + store_->CancelRequest(request_);
|
| + request_ = NULL;
|
| + callback_.Reset();
|
| + }
|
| +}
|
| +
|
| +void DTLSIdentityStore::RequestHandle::RequestStarted(
|
| + DTLSIdentityStore* store,
|
| + DTLSIdentityRequest* request,
|
| + const CompletionCallback& callback) {
|
| + DCHECK(!request_);
|
| + store_ = store;
|
| + request_ = request;
|
| + callback_ = callback;
|
| +}
|
| +
|
| +void DTLSIdentityStore::RequestHandle::OnRequestComplete(
|
| + int error,
|
| + const std::string& certificate,
|
| + const std::string& private_key) {
|
| + request_ = NULL;
|
| + base::ResetAndReturn(&callback_).Run(error, certificate, private_key);
|
| +}
|
| +
|
| +DTLSIdentityStore::DTLSIdentityStore()
|
| + : task_runner_(base::WorkerPool::GetTaskRunner(true)) {
|
| +}
|
| +
|
| +DTLSIdentityStore::~DTLSIdentityStore() {}
|
| +
|
| +void DTLSIdentityStore::RequestIdentity(const GURL& origin,
|
| + const std::string& identity_name,
|
| + const std::string& common_name,
|
| + const CompletionCallback& callback,
|
| + RequestHandle* out_request) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + // TODO(jiayl): find the cert in the persistent store and generate a new one
|
| + // only when not found.
|
| + DTLSIdentityRequest* request = new DTLSIdentityRequest(
|
| + base::Bind(&RequestHandle::OnRequestComplete,
|
| + base::Unretained(out_request)));
|
| + out_request->RequestStarted(this, request, callback);
|
| +
|
| + DTLSIdentityRequestResult* result = new DTLSIdentityRequestResult;
|
| + task_runner_->PostTaskAndReply(
|
| + FROM_HERE,
|
| + base::Bind(&GenerateIdentityWorker, common_name, result),
|
| + base::Bind(&DTLSIdentityRequest::Post,
|
| + base::Owned(request), base::Owned(result)));
|
| +}
|
| +
|
| +void DTLSIdentityStore::CancelRequest(DTLSIdentityRequest* request) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + request->Cancel();
|
| +}
|
| +
|
| +DTLSIdentityStore::DTLSIdentityStore(
|
| + const scoped_refptr<base::TaskRunner>& task_runner)
|
| + : task_runner_(task_runner) {
|
| +}
|
| +
|
| +} // namespace content
|
|
|