Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1353)

Unified Diff: chrome/browser/net/certificate_error_reporter.cc

Issue 1083493003: Encrypt certificate reports before uploading to HTTP URLs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add aead files to BUILD.gn Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/net/certificate_error_reporter.cc
diff --git a/chrome/browser/net/certificate_error_reporter.cc b/chrome/browser/net/certificate_error_reporter.cc
index 279209c6ba2499c781eec14d720e7b02d9f5e3a2..edff489f4ca0762dac6eb03bf554a1bc7e0adef2 100644
--- a/chrome/browser/net/certificate_error_reporter.cc
+++ b/chrome/browser/net/certificate_error_reporter.cc
@@ -10,6 +10,14 @@
#include "base/stl_util.h"
#include "base/time/time.h"
#include "chrome/browser/net/cert_logger.pb.h"
+
+#if defined(USE_OPENSSL)
+#include "crypto/aead_openssl.h"
+#endif
+
+#include "crypto/curve25519.h"
+#include "crypto/hkdf.h"
+#include "crypto/random.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
@@ -18,15 +26,87 @@
#include "net/ssl/ssl_info.h"
#include "net/url_request/url_request_context.h"
+namespace {
+
+// Constants used for crypto
+static const uint8 kServerPublicKey[] = {
+ 0x51, 0xcc, 0x52, 0x67, 0x42, 0x47, 0x3b, 0x10, 0xe8, 0x63, 0x18,
+ 0x3c, 0x61, 0xa7, 0x96, 0x76, 0x86, 0x91, 0x40, 0x71, 0x39, 0x5f,
+ 0x31, 0x1a, 0x39, 0x5b, 0x76, 0xb1, 0x6b, 0x3d, 0x6a, 0x2b};
+static const uint32 kServerPublicKeyVersion = 1;
+
+#if defined(USE_OPENSSL)
+
+static const char kHkdfLabel[] = "certificate report";
+
+bool EncryptSerializedReport(
+ const uint8* server_public_key,
+ uint32 server_public_key_version,
+ const std::string& report,
+ chrome_browser_net::EncryptedCertLoggerRequest* encrypted_report) {
+ // Generate an ephemeral key pair to generate a shared secret.
+ uint8 public_key[crypto::curve25519::kBytes];
+ uint8 private_key[crypto::curve25519::kScalarBytes];
+ uint8 shared_secret[crypto::curve25519::kBytes];
+
+ crypto::RandBytes(private_key, sizeof(private_key));
+ crypto::curve25519::ScalarBaseMult(private_key, public_key);
+ crypto::curve25519::ScalarMult(private_key, server_public_key, shared_secret);
+
+ crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
+ crypto::HKDF hkdf(std::string((char*)shared_secret, sizeof(shared_secret)),
+ kHkdfLabel, std::string(), 0, 0, aead.KeyLength());
+
+ const std::string key(hkdf.subkey_secret().data(),
+ hkdf.subkey_secret().size());
+ aead.Init(&key);
+
+ // Use an all-zero nonce because the key is random per-message.
+ std::string nonce(aead.NonceLength(), 0);
+
+ std::string ciphertext;
+ if (!aead.Seal(report, nonce, "", &ciphertext)) {
+ LOG(ERROR) << "Error sealing certificate report.";
+ return false;
+ }
+
+ encrypted_report->set_encrypted_report(ciphertext);
+ encrypted_report->set_server_public_key_version(server_public_key_version);
+ encrypted_report->set_client_public_key(
+ std::string((char*)public_key, sizeof(public_key)));
+ encrypted_report->set_algorithm(
+ chrome_browser_net::EncryptedCertLoggerRequest::
+ AEAD_ECDH_AES_128_CTR_HMAC_SHA256);
+ return true;
+}
+#endif
+
+} // namespace
+
namespace chrome_browser_net {
CertificateErrorReporter::CertificateErrorReporter(
net::URLRequestContext* request_context,
const GURL& upload_url,
CookiesPreference cookies_preference)
+ : CertificateErrorReporter(request_context,
+ upload_url,
+ cookies_preference,
+ kServerPublicKey,
+ kServerPublicKeyVersion) {
+}
+
+CertificateErrorReporter::CertificateErrorReporter(
+ net::URLRequestContext* request_context,
+ const GURL& upload_url,
+ CookiesPreference cookies_preference,
+ const uint8 server_public_key[32],
+ const uint32 server_public_key_version)
: request_context_(request_context),
upload_url_(upload_url),
- cookies_preference_(cookies_preference) {
+ cookies_preference_(cookies_preference),
+ server_public_key_(server_public_key),
+ server_public_key_version_(server_public_key_version) {
DCHECK(!upload_url.is_empty());
}
@@ -38,8 +118,6 @@ void CertificateErrorReporter::SendReport(ReportType type,
const std::string& hostname,
const net::SSLInfo& ssl_info) {
CertLoggerRequest request;
- std::string out;
-
BuildReport(hostname, ssl_info, &request);
switch (type) {
@@ -47,9 +125,25 @@ void CertificateErrorReporter::SendReport(ReportType type,
SendCertLoggerRequest(request);
break;
case REPORT_TYPE_EXTENDED_REPORTING:
- // TODO(estark): Encrypt the report if not sending over HTTPS.
- DCHECK(upload_url_.SchemeIsCryptographic());
- SendCertLoggerRequest(request);
+ if (upload_url_.SchemeIsCryptographic()) {
+ SendCertLoggerRequest(request);
+ } else {
+ DCHECK(IsHttpUploadUrlSupported());
+#if defined(USE_OPENSSL)
+ EncryptedCertLoggerRequest encrypted_report;
+ std::string serialized_report;
+ request.SerializeToString(&serialized_report);
+ if (!EncryptSerializedReport(server_public_key_,
+ server_public_key_version_,
+ serialized_report, &encrypted_report)) {
+ LOG(ERROR) << "Failed to encrypt serialized report.";
+ return;
+ }
+ std::string serialized_encrypted_report;
+ encrypted_report.SerializeToString(&serialized_encrypted_report);
+ SendSerializedRequest(serialized_encrypted_report);
+#endif
+ }
break;
default:
NOTREACHED();
@@ -84,11 +178,55 @@ scoped_ptr<net::URLRequest> CertificateErrorReporter::CreateURLRequest(
return request.Pass();
}
+bool CertificateErrorReporter::IsHttpUploadUrlSupported() {
+#if defined(USE_OPENSSL)
+ return true;
+#else
+ return false;
+#endif
+}
+
+// Used only by tests.
+#if defined(USE_OPENSSL)
+bool CertificateErrorReporter::DecryptCertificateErrorReport(
+ const uint8 server_private_key[32],
+ const EncryptedCertLoggerRequest& encrypted_report,
+ CertLoggerRequest* decrypted_report) {
+ uint8 shared_secret[crypto::curve25519::kBytes];
+ crypto::curve25519::ScalarMult(
+ server_private_key, (uint8*)encrypted_report.client_public_key().data(),
+ shared_secret);
+
+ crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
+ crypto::HKDF hkdf(std::string((char*)shared_secret, sizeof(shared_secret)),
+ kHkdfLabel, std::string(), 0, 0, aead.KeyLength());
+
+ const std::string key(hkdf.subkey_secret().data(),
+ hkdf.subkey_secret().size());
+ aead.Init(&key);
+
+ // Use an all-zero nonce because the key is random per-message.
+ std::string nonce(aead.NonceLength(), 0);
+
+ std::string plaintext;
+ if (!aead.Open(encrypted_report.encrypted_report(), nonce, "", &plaintext)) {
+ LOG(ERROR) << "Error opening certificate report";
+ return false;
+ }
+
+ return decrypted_report->ParseFromString(plaintext);
+}
+#endif
+
void CertificateErrorReporter::SendCertLoggerRequest(
const CertLoggerRequest& request) {
std::string serialized_request;
request.SerializeToString(&serialized_request);
+ SendSerializedRequest(serialized_request);
+}
+void CertificateErrorReporter::SendSerializedRequest(
+ const std::string& serialized_request) {
scoped_ptr<net::URLRequest> url_request = CreateURLRequest(request_context_);
url_request->set_method("POST");
« no previous file with comments | « chrome/browser/net/certificate_error_reporter.h ('k') | chrome/browser/net/certificate_error_reporter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698