Commit 0a3351c2 authored by estark's avatar estark Committed by Commit bot

Encrypt certificate reports before uploading to HTTP URLs

This CL introduces a new protobuf to store encrypted
CertLoggerRequests. Serialized certificate reports are encrypted with an
AES-CTR-128-HMAC-SHA256 AEAD (from BoringSSL, thus encrypted reports are
only supported on BoringSSL platforms) before being uploaded to HTTP
endpoints. |CertificateErrorReporter::IsHttpUploadUrlSupported| allows
users of the class to set an HTTP URL if supported.

BUG=461590

Review URL: https://codereview.chromium.org/1083493003

Cr-Commit-Position: refs/heads/master@{#326876}
parent 5ae13f42
......@@ -41,6 +41,24 @@ message CertLoggerRequest {
repeated string pin = 5;
};
// A wrapper proto containing an encrypted CertLoggerRequest
message EncryptedCertLoggerRequest {
// An encrypted, serialized CertLoggerRequest
required bytes encrypted_report = 1;
// The server public key version that was used to derive the shared secret.
required uint32 server_public_key_version = 2;
// The client public key that corresponds to the private key that was used
// to derive the shared secret.
required bytes client_public_key = 3;
// The encryption algorithm used to encrypt the report.
enum Algorithm {
UNKNOWN_ALGORITHM = 0;
AEAD_ECDH_AES_128_CTR_HMAC_SHA256 = 1;
}
optional Algorithm algorithm = 4
[default = AEAD_ECDH_AES_128_CTR_HMAC_SHA256];
};
// The response sent back to the user.
message CertLoggerResponse {
enum ResponseCode {
......@@ -53,4 +71,3 @@ message CertLoggerResponse {
};
required ResponseCode response = 1;
};
......@@ -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");
......
......@@ -21,6 +21,7 @@ class SSLInfo;
namespace chrome_browser_net {
class CertLoggerRequest;
class EncryptedCertLoggerRequest;
// Provides functionality for sending reports about invalid SSL
// certificate chains to a report collection server.
......@@ -48,6 +49,13 @@ class CertificateErrorReporter : public net::URLRequest::Delegate {
const GURL& upload_url,
CookiesPreference cookies_preference);
// Allows tests to use a server public key with known private key.
CertificateErrorReporter(net::URLRequestContext* request_context,
const GURL& upload_url,
CookiesPreference cookies_preference,
const uint8 server_public_key[32],
const uint32 server_public_key_version);
~CertificateErrorReporter() override;
// Construct, serialize, and send a certificate report to the report
......@@ -58,6 +66,11 @@ class CertificateErrorReporter : public net::URLRequest::Delegate {
// responsible for enforcing any preconditions (such as obtaining user
// opt-in, only sending reports for certain hostnames, checking for
// incognito mode, etc.).
//
// On some platforms (but not all), CertificateErrorReporter can use
// an HTTP endpoint to send encrypted extended reporting reports. On
// unsupported platforms, callers must send extended reporting reports
// over SSL.
virtual void SendReport(ReportType type,
const std::string& hostname,
const net::SSLInfo& ssl_info);
......@@ -66,6 +79,16 @@ class CertificateErrorReporter : public net::URLRequest::Delegate {
void OnResponseStarted(net::URLRequest* request) override;
void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
// Callers can use this method to determine if sending reports over
// HTTP is supported.
static bool IsHttpUploadUrlSupported();
// Used by tests.
static bool DecryptCertificateErrorReport(
const uint8 server_private_key[32],
const EncryptedCertLoggerRequest& encrypted_report,
CertLoggerRequest* decrypted_report);
private:
// Create a URLRequest with which to send a certificate report to the
// server.
......@@ -76,6 +99,8 @@ class CertificateErrorReporter : public net::URLRequest::Delegate {
// collection server.
void SendCertLoggerRequest(const CertLoggerRequest& request);
void SendSerializedRequest(const std::string& serialized_request);
// Populate the CertLoggerRequest for a report.
static void BuildReport(const std::string& hostname,
const net::SSLInfo& ssl_info,
......@@ -92,6 +117,9 @@ class CertificateErrorReporter : public net::URLRequest::Delegate {
CookiesPreference cookies_preference_;
const uint8* server_public_key_;
const uint32 server_public_key_version_;
DISALLOW_COPY_AND_ASSIGN(CertificateErrorReporter);
};
......
......@@ -19,6 +19,7 @@
#include "chrome/browser/net/cert_logger.pb.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/curve25519.h"
#include "net/base/load_flags.h"
#include "net/base/network_delegate_impl.h"
#include "net/base/test_data_directory.h"
......@@ -47,6 +48,7 @@ const char kHostname[] = "test.mail.google.com";
const char kSecondRequestHostname[] = "test2.mail.google.com";
const char kDummyFailureLog[] = "dummy failure log";
const char kTestCertFilename[] = "test_mail_google_com.pem";
const uint32 kServerPublicKeyVersion = 1;
SSLInfo GetTestSSLInfo() {
SSLInfo info;
......@@ -83,7 +85,9 @@ void EnableUrlRequestMocks(bool enable) {
// |GetTestSSLInfo()|). The hostname sent in the report will be erased
// from |expect_hostnames|.
void CheckUploadData(URLRequest* request,
std::set<std::string>* expect_hostnames) {
std::set<std::string>* expect_hostnames,
bool encrypted,
const uint8* server_private_key) {
const net::UploadDataStream* upload = request->get_upload();
ASSERT_TRUE(upload);
ASSERT_TRUE(upload->GetElementReaders());
......@@ -93,9 +97,27 @@ void CheckUploadData(URLRequest* request,
(*upload->GetElementReaders())[0]->AsBytesReader();
ASSERT_TRUE(reader);
std::string upload_data(reader->bytes(), reader->length());
chrome_browser_net::CertLoggerRequest uploaded_request;
uploaded_request.ParseFromString(upload_data);
chrome_browser_net::CertLoggerRequest uploaded_request;
#if defined(USE_OPENSSL)
if (encrypted) {
chrome_browser_net::EncryptedCertLoggerRequest encrypted_request;
encrypted_request.ParseFromString(upload_data);
EXPECT_EQ(kServerPublicKeyVersion,
encrypted_request.server_public_key_version());
EXPECT_EQ(chrome_browser_net::EncryptedCertLoggerRequest::
AEAD_ECDH_AES_128_CTR_HMAC_SHA256,
encrypted_request.algorithm());
ASSERT_TRUE(
chrome_browser_net::CertificateErrorReporter::
DecryptCertificateErrorReport(server_private_key, encrypted_request,
&uploaded_request));
} else {
ASSERT_TRUE(uploaded_request.ParseFromString(upload_data));
}
#else
ASSERT_TRUE(uploaded_request.ParseFromString(upload_data));
#endif
EXPECT_EQ(1u, expect_hostnames->count(uploaded_request.hostname()));
expect_hostnames->erase(uploaded_request.hostname());
......@@ -116,7 +138,11 @@ class TestCertificateErrorReporterNetworkDelegate : public NetworkDelegateImpl {
: url_request_destroyed_callback_(base::Bind(&base::DoNothing)),
all_url_requests_destroyed_callback_(base::Bind(&base::DoNothing)),
num_requests_(0),
expect_cookies_(false) {}
expect_cookies_(false),
expect_request_encrypted_(false) {
memset(server_private_key_, 1, sizeof(server_private_key_));
crypto::curve25519::ScalarBaseMult(server_private_key_, server_public_key_);
}
~TestCertificateErrorReporterNetworkDelegate() override {}
......@@ -145,6 +171,10 @@ class TestCertificateErrorReporterNetworkDelegate : public NetworkDelegateImpl {
expect_cookies_ = expect_cookies;
}
void set_expect_request_encrypted(bool expect_request_encrypted) {
expect_request_encrypted_ = expect_request_encrypted;
}
// NetworkDelegateImpl implementation
int OnBeforeURLRequest(URLRequest* request,
const CompletionCallback& callback,
......@@ -162,7 +192,8 @@ class TestCertificateErrorReporterNetworkDelegate : public NetworkDelegateImpl {
}
std::string uploaded_request_hostname;
CheckUploadData(request, &expect_hostnames_);
CheckUploadData(request, &expect_hostnames_, expect_request_encrypted_,
server_private_key_);
expect_hostnames_.erase(uploaded_request_hostname);
return net::OK;
}
......@@ -173,6 +204,8 @@ class TestCertificateErrorReporterNetworkDelegate : public NetworkDelegateImpl {
all_url_requests_destroyed_callback_.Run();
}
const uint8* server_public_key() { return server_public_key_; }
private:
base::Closure url_request_destroyed_callback_;
base::Closure all_url_requests_destroyed_callback_;
......@@ -180,6 +213,10 @@ class TestCertificateErrorReporterNetworkDelegate : public NetworkDelegateImpl {
GURL expect_url_;
std::set<std::string> expect_hostnames_;
bool expect_cookies_;
bool expect_request_encrypted_;
uint8 server_public_key_[32];
uint8 server_private_key_[32];
DISALLOW_COPY_AND_ASSIGN(TestCertificateErrorReporterNetworkDelegate);
};
......@@ -237,11 +274,24 @@ TEST_F(CertificateErrorReporterTest, PinningViolationSendReportSendsRequest) {
}
TEST_F(CertificateErrorReporterTest, ExtendedReportingSendReportSendsRequest) {
GURL url = net::URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
CertificateErrorReporter reporter(
context(), url, CertificateErrorReporter::DO_NOT_SEND_COOKIES);
SendReport(&reporter, network_delegate(), kHostname, url, 0,
// Data should not be encrypted when sent to an HTTPS URL.
GURL https_url = net::URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
CertificateErrorReporter https_reporter(
context(), https_url, CertificateErrorReporter::DO_NOT_SEND_COOKIES);
network_delegate()->set_expect_request_encrypted(false);
SendReport(&https_reporter, network_delegate(), kHostname, https_url, 0,
CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING);
// Data should be encrypted when sent to an HTTP URL.
if (CertificateErrorReporter::IsHttpUploadUrlSupported()) {
GURL http_url = net::URLRequestMockDataJob::GetMockHttpUrl("dummy data", 1);
CertificateErrorReporter http_reporter(
context(), http_url, CertificateErrorReporter::DO_NOT_SEND_COOKIES,
network_delegate()->server_public_key(), kServerPublicKeyVersion);
network_delegate()->set_expect_request_encrypted(true);
SendReport(&http_reporter, network_delegate(), kHostname, http_url, 1,
CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING);
}
}
TEST_F(CertificateErrorReporterTest, SendMultipleReportsSequentially) {
......
......@@ -24,8 +24,12 @@ using chrome_browser_net::CertificateErrorReporter;
using content::BrowserThread;
namespace {
// URL to upload invalid certificate chain reports
const char kExtendedReportingUploadUrl[] =
// URLs to upload invalid certificate chain reports. The HTTP URL is
// preferred since a client seeing an invalid cert might not be able to
// make an HTTPS connection to report it.
// TODO(estark): insert the production HTTP URL when it's ready
const char kExtendedReportingUploadUrlInsecure[] = "";
const char kExtendedReportingUploadUrlSecure[] =
"https://sb-ssl.google.com/safebrowsing/clientreport/chrome-certs";
} // namespace
......@@ -44,16 +48,22 @@ SafeBrowsingPingManager::SafeBrowsingPingManager(
const SafeBrowsingProtocolConfig& config)
: client_name_(config.client_name),
request_context_getter_(request_context_getter),
url_prefix_(config.url_prefix),
certificate_error_reporter_(
request_context_getter
? new CertificateErrorReporter(
request_context_getter->GetURLRequestContext(),
GURL(kExtendedReportingUploadUrl),
CertificateErrorReporter::SEND_COOKIES)
: nullptr) {
url_prefix_(config.url_prefix) {
DCHECK(!url_prefix_.empty());
if (request_context_getter) {
bool use_insecure_certificate_upload_url =
CertificateErrorReporter::IsHttpUploadUrlSupported() &&
strlen(kExtendedReportingUploadUrlInsecure) > 0;
GURL certificate_upload_url(use_insecure_certificate_upload_url
? kExtendedReportingUploadUrlInsecure
: kExtendedReportingUploadUrlSecure);
certificate_error_reporter_.reset(new CertificateErrorReporter(
request_context_getter->GetURLRequestContext(), certificate_upload_url,
CertificateErrorReporter::SEND_COOKIES));
}
version_ = SafeBrowsingProtocolManagerHelper::Version();
}
......
// Copyright 2015 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 "crypto/aead_openssl.h"
#if defined(USE_OPENSSL)
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <string>
#include "base/basictypes.h"
#include "base/strings/string_util.h"
#include "crypto/openssl_util.h"
namespace crypto {
Aead::Aead(AeadAlgorithm algorithm) : key_(nullptr) {
EnsureOpenSSLInit();
switch (algorithm) {
case AES_128_CTR_HMAC_SHA256:
aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
break;
}
}
Aead::~Aead() {
}
void Aead::Init(const std::string* key) {
DCHECK(!key_);
DCHECK_EQ(KeyLength(), key->size());
key_ = key;
}
bool Aead::Seal(const base::StringPiece& plaintext,
const base::StringPiece& nonce,
const base::StringPiece& additional_data,
std::string* ciphertext) const {
DCHECK(key_);
DCHECK_EQ(NonceLength(), nonce.size());
EVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init(&ctx, aead_,
reinterpret_cast<const uint8*>(key_->data()),
key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
return false;
}
std::string result;
const size_t max_output_length =
EVP_AEAD_max_overhead(aead_) + plaintext.size();
size_t output_length;
uint8* out_ptr =
reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1));
if (!EVP_AEAD_CTX_seal(
&ctx, out_ptr, &output_length, max_output_length,
reinterpret_cast<const uint8*>(nonce.data()), nonce.size(),
reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(),
reinterpret_cast<const uint8*>(additional_data.data()),
additional_data.size())) {
EVP_AEAD_CTX_cleanup(&ctx);
return false;
}
DCHECK_LE(output_length, max_output_length);
result.resize(output_length);
ciphertext->swap(result);
EVP_AEAD_CTX_cleanup(&ctx);
return true;
}
bool Aead::Open(const base::StringPiece& ciphertext,
const base::StringPiece& nonce,
const base::StringPiece& additional_data,
std::string* plaintext) const {
DCHECK(key_);
EVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init(&ctx, aead_,
reinterpret_cast<const uint8*>(key_->data()),
key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
return false;
}
std::string result;
const size_t max_output_length = ciphertext.size();
size_t output_length;
uint8* out_ptr =
reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1));
if (!EVP_AEAD_CTX_open(
&ctx, out_ptr, &output_length, max_output_length,
reinterpret_cast<const uint8*>(nonce.data()), nonce.size(),
reinterpret_cast<const uint8*>(ciphertext.data()), ciphertext.size(),
reinterpret_cast<const uint8*>(additional_data.data()),
additional_data.size())) {
EVP_AEAD_CTX_cleanup(&ctx);
return false;
}
DCHECK_LE(output_length, max_output_length);
result.resize(output_length);
plaintext->swap(result);
EVP_AEAD_CTX_cleanup(&ctx);
return true;
}
size_t Aead::KeyLength() const {
return EVP_AEAD_key_length(aead_);
}
size_t Aead::NonceLength() const {
return EVP_AEAD_nonce_length(aead_);
}
} // namespace
#endif
// Copyright 2015 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.
#ifndef CRYPTO_AEAD_H_
#define CRYPTO_AEAD_H_
#include "base/strings/string_piece.h"
#include "crypto/crypto_export.h"
struct evp_aead_st;
namespace crypto {
// This class exposes the AES-128-CTR-HMAC-SHA256 AEAD, currently only
// for OpenSSL builds.
class CRYPTO_EXPORT Aead {
public:
enum AeadAlgorithm { AES_128_CTR_HMAC_SHA256 };
explicit Aead(AeadAlgorithm algorithm);
~Aead();
void Init(const std::string* key);
bool Seal(const base::StringPiece& plaintext,
const base::StringPiece& nonce,
const base::StringPiece& additional_data,
std::string* ciphertext) const;
bool Open(const base::StringPiece& ciphertext,
const base::StringPiece& nonce,
const base::StringPiece& additional_data,
std::string* plaintext) const;
size_t KeyLength() const;
size_t NonceLength() const;
private:
const std::string* key_;
const evp_aead_st* aead_;
};
} // namespace crypto
#endif // CRYPTO_ENCRYPTOR_H_
// Copyright 2015 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 "crypto/aead_openssl.h"
#include <string>
#include "testing/gtest/include/gtest/gtest.h"
namespace {
#if defined(USE_OPENSSL)
TEST(AeadTest, SealOpen) {
crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
std::string key(aead.KeyLength(), 0);
aead.Init(&key);
std::string nonce(aead.NonceLength(), 0);
std::string plaintext("this is the plaintext");
std::string ad("this is the additional data");
std::string ciphertext;
EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext));
EXPECT_LT(0U, ciphertext.size());
std::string decrypted;
EXPECT_TRUE(aead.Open(ciphertext, nonce, ad, &decrypted));
EXPECT_EQ(plaintext, decrypted);
}
TEST(AeadTest, SealOpenWrongKey) {
crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
std::string key(aead.KeyLength(), 0);
std::string wrong_key(aead.KeyLength(), 1);
aead.Init(&key);
crypto::Aead aead_wrong_key(crypto::Aead::AES_128_CTR_HMAC_SHA256);
aead_wrong_key.Init(&wrong_key);
std::string nonce(aead.NonceLength(), 0);
std::string plaintext("this is the plaintext");
std::string ad("this is the additional data");
std::string ciphertext;
EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext));
EXPECT_LT(0U, ciphertext.size());
std::string decrypted;
EXPECT_FALSE(aead_wrong_key.Open(ciphertext, nonce, ad, &decrypted));
EXPECT_EQ(0U, decrypted.size());
}
#endif
} // namespace
......@@ -125,6 +125,8 @@
],
}, {
'sources!': [
'aead_openssl.cc',
'aead_openssl.h',
'ec_private_key_openssl.cc',
'ec_signature_creator_openssl.cc',
'encryptor_openssl.cc',
......@@ -158,6 +160,7 @@
'target_name': 'crypto_unittests',
'type': 'executable',
'sources': [
'aead_openssl_unittest.cc',
'curve25519_unittest.cc',
'ec_private_key_unittest.cc',
'ec_signature_creator_unittest.cc',
......
......@@ -27,6 +27,8 @@
# NOTE: all transitive dependencies of HMAC on windows need
# to be placed in the source list above.
'<@(hmac_win64_related_sources)',
'aead_openssl.cc',
'aead_openssl.h',
'apple_keychain.h',
'apple_keychain_ios.mm',
'apple_keychain_mac.mm',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment