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

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

Issue 975623002: Encrypt certificate logger requests for extended reporting (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove stray comment Created 5 years, 10 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/chrome_fraudulent_certificate_reporter.cc
diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
index 0e3a1d658533a4678f51c441ac05704cf2651547..e3f43613170f3157b583743f15270b634e2d2ed7 100644
--- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
+++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
@@ -12,6 +12,12 @@
#include "base/stl_util.h"
#include "base/time/time.h"
#include "chrome/browser/net/cert_logger.pb.h"
+#include "crypto/curve25519.h"
+#include "crypto/encryptor.h"
+#include "crypto/hmac.h"
+#include "crypto/random.h"
+#include "crypto/sha2.h"
+#include "crypto/symmetric_key.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
@@ -29,6 +35,14 @@ static const char kFraudulentCertificateUploadEndpoint[] =
static const char kInvalidCertificateChainUploadEndpoint[] = "";
+// Constants used for crypto
+static const uint8 kServerPublicKey[] = {
+ 0xc5, 0x3e, 0x58, 0x9e, 0x43, 0xec, 0xbc, 0x84, 0xff, 0xec, 0x8d,
+ 0x57, 0x20, 0xa3, 0x61, 0x60, 0xe1, 0x0b, 0x7d, 0x30, 0x5d, 0x3b,
+ 0x2a, 0x90, 0xcf, 0x73, 0xe7, 0x61, 0xa8, 0x92, 0xa1, 0x79};
+static const uint32 kServerPublicKeyVersion = 1;
+static const uint32 kAesNonceSize = 16;
+
ChromeFraudulentCertificateReporter::ChromeFraudulentCertificateReporter(
net::URLRequestContext* request_context)
: request_context_(request_context),
@@ -40,6 +54,76 @@ ChromeFraudulentCertificateReporter::~ChromeFraudulentCertificateReporter() {
STLDeleteElements(&inflight_requests_);
}
+void CalculateSymmetricKeys(const uint8* client_private_key,
+ const uint8* server_public_key,
+ std::string& aes_key,
+ std::string& hmac_key) {
+ uint8 shared_secret[crypto::curve25519::kBytes];
+ uint8 symmetric_key[crypto::kSHA256Length];
+ crypto::curve25519::ScalarMult(client_private_key, server_public_key,
+ shared_secret);
+ crypto::SHA256HashString(
+ std::string((char*)shared_secret, sizeof(shared_secret)), symmetric_key,
+ sizeof(symmetric_key));
+
+ aes_key = std::string((char*)symmetric_key, sizeof(symmetric_key) / 2);
+ hmac_key = std::string((char*)(symmetric_key + sizeof(symmetric_key) / 2),
agl 2015/03/05 19:22:25 An HMAC-SHA256 key is generally 32 bytes. Also, if
+ sizeof(symmetric_key) / 2);
+}
+
+bool EncryptSerializedReport(const uint8* server_public_key,
+ uint32 server_public_key_version,
+ const std::string& report,
+ 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];
+ crypto::RandBytes(private_key, sizeof(private_key));
+ crypto::curve25519::ScalarBaseMult(private_key, public_key);
+
+ // Calculate the shared symmetric keys.
+ std::string aes_key_str;
+ std::string hmac_key;
+ CalculateSymmetricKeys(private_key, server_public_key, aes_key_str, hmac_key);
+ scoped_ptr<crypto::SymmetricKey> aes_key(
+ crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, aes_key_str));
+
+ // Encrypt the serialized report with AES-CTR.
+ crypto::Encryptor encryptor;
+ char counter[kAesNonceSize];
agl 2015/03/05 19:22:25 s/char/uint8/
+ std::string ciphertext;
+ crypto::RandBytes(counter, kAesNonceSize);
agl 2015/03/05 19:22:25 as noted, the nonce can be all zeros because the k
+ encryptor.Init(aes_key.get(), crypto::Encryptor::CTR, "");
+ encryptor.SetCounter(std::string(counter, kAesNonceSize));
+ encryptor.Encrypt(report, &ciphertext);
+
+ // Compute HMAC-SHA256(nonce || ciphertext).
+ std::string hmac_input = std::string(counter, kAesNonceSize) + ciphertext;
+ crypto::HMAC hmac(crypto::HMAC::SHA256);
+ bool init_result = hmac.Init(hmac_key);
agl 2015/03/05 19:22:25 why does |init_result| and |hmac_result| exist? Yo
+ if (!init_result) {
+ LOG(ERROR) << "Failed to initialize HMAC.";
+ return init_result;
+ }
+
+ unsigned char digest[hmac.DigestLength()];
agl 2015/03/05 19:22:25 Aren't variable-length arrays a compiler extension
+ bool hmac_result = hmac.Sign(hmac_input, digest, sizeof(digest));
+ if (!hmac_result) {
+ LOG(ERROR) << "Failed to compute HMAC.";
+ return hmac_result;
+ }
+
+ encrypted_report.set_encrypted_report(ciphertext);
+ encrypted_report.set_server_public_key(server_public_key_version);
+ encrypted_report.set_client_public_key(
+ std::string((char*)public_key, crypto::curve25519::kBytes));
+ encrypted_report.set_nonce(std::string(counter, kAesNonceSize));
+ encrypted_report.set_mac(std::string((char*)digest, sizeof(digest)));
+ encrypted_report.set_algorithm(
+ EncryptedCertLoggerRequest::ECDH_AES_CTR_128_HMAC_SHA256);
+ return true;
+}
+
static std::string BuildReport(const std::string& hostname,
const net::SSLInfo& ssl_info) {
CertLoggerRequest request;
@@ -77,24 +161,37 @@ void ChromeFraudulentCertificateReporter::SendReport(
ReportType type,
const std::string& hostname,
const net::SSLInfo& ssl_info) {
+ // We do silent/automatic reporting ONLY for Google properties. For other
+ // domains (when we start supporting that), we will ask for user permission.
+ if (type == REPORT_TYPE_PIN_VIOLATION &&
+ !net::TransportSecurityState::IsGooglePinnedProperty(hostname)) {
+ return;
+ }
+
+ std::string report = BuildReport(hostname, ssl_info);
+
if (type == REPORT_TYPE_EXTENDED_REPORTING) {
// TODO(estark): Double-check that the user is opted in.
// TODO(estark): Temporarily, since there is no upload endpoint, just log
// the information.
- LOG(ERROR) << "SSL report for " << hostname << ":\n"
- << BuildReport(hostname, ssl_info) << "\n\n";
- return;
- }
+ LOG(ERROR) << "SSL report for " << hostname << ":\n" << report << "\n\n";
+
+ EncryptedCertLoggerRequest encrypted_request;
+ bool result = EncryptSerializedReport(
+ kServerPublicKey, kServerPublicKeyVersion, report, encrypted_request);
+ if (!result) {
+ LOG(ERROR) << "Failed to encrypt serialized report.";
+ return;
+ }
+
+ std::string encrypted_report;
+ encrypted_request.SerializeToString(&encrypted_report);
+ LOG(ERROR) << "Encrypted: " << encrypted_report;
- // We do silent/automatic reporting ONLY for Google properties. For other
- // domains (when we start supporting that), we will ask for user permission.
- if (!net::TransportSecurityState::IsGooglePinnedProperty(hostname)) {
return;
}
- std::string report = BuildReport(hostname, ssl_info);
-
scoped_ptr<net::URLRequest> url_request =
CreateURLRequest(request_context_, pinning_violation_upload_url_);
url_request->set_method("POST");

Powered by Google App Engine
This is Rietveld 408576698