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

Unified Diff: net/base/origin_bound_cert_service_unittest.cc

Issue 8662036: Support EC certs in OriginBoundCertService and OriginBoundCertStore. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: forgot to add new file Created 9 years 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: net/base/origin_bound_cert_service_unittest.cc
diff --git a/net/base/origin_bound_cert_service_unittest.cc b/net/base/origin_bound_cert_service_unittest.cc
index 3fdb443cf3cb0e77beebf9c454f2eec822ec1360..c5ca7b664d0ca814b5ee9b70c458b766114f7a7b 100644
--- a/net/base/origin_bound_cert_service_unittest.cc
+++ b/net/base/origin_bound_cert_service_unittest.cc
@@ -9,7 +9,9 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
+#include "crypto/ec_private_key.h"
#include "crypto/rsa_private_key.h"
+#include "net/base/asn1_util.h"
#include "net/base/default_origin_bound_cert_store.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -33,53 +35,178 @@ TEST(OriginBoundCertServiceTest, CacheHit) {
std::string origin("https://encrypted.google.com:443");
int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_RSA_SIGN);
TestCompletionCallback callback;
OriginBoundCertService::RequestHandle request_handle;
// Asynchronous completion.
+ SSLClientCertType type1;
std::string private_key_info1, der_cert1;
EXPECT_EQ(0, service->cert_count());
error = service->GetOriginBoundCert(
- origin, &private_key_info1, &der_cert1, callback.callback(),
- &request_handle);
+ origin, types, &type1, &private_key_info1, &der_cert1,
+ callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle != NULL);
error = callback.WaitForResult();
EXPECT_EQ(OK, error);
EXPECT_EQ(1, service->cert_count());
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type1);
EXPECT_FALSE(private_key_info1.empty());
EXPECT_FALSE(der_cert1.empty());
// Synchronous completion.
+ SSLClientCertType type2;
+ // If we request EC and RSA, should still retrieve the RSA cert.
+ types.insert(types.begin(), CLIENT_CERT_ECDSA_SIGN);
std::string private_key_info2, der_cert2;
error = service->GetOriginBoundCert(
- origin, &private_key_info2, &der_cert2, callback.callback(),
- &request_handle);
+ origin, types, &type2, &private_key_info2, &der_cert2,
+ callback.callback(), &request_handle);
EXPECT_TRUE(request_handle == NULL);
EXPECT_EQ(OK, error);
EXPECT_EQ(1, service->cert_count());
-
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type2);
EXPECT_EQ(private_key_info1, private_key_info2);
EXPECT_EQ(der_cert1, der_cert2);
- EXPECT_EQ(2u, service->requests());
- EXPECT_EQ(1u, service->cert_store_hits());
+ // Request only EC. Should generate a new EC cert and discard the old RSA
+ // cert.
+ SSLClientCertType type3;
+ types.pop_back(); // Remove CLIENT_CERT_RSA_SIGN from requested types.
+ std::string private_key_info3, der_cert3;
+ EXPECT_EQ(1, service->cert_count());
+ error = service->GetOriginBoundCert(
+ origin, types, &type3, &private_key_info3, &der_cert3,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service->cert_count());
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3);
+ EXPECT_FALSE(private_key_info1.empty());
+ EXPECT_FALSE(der_cert1.empty());
+ EXPECT_NE(private_key_info1, private_key_info3);
+ EXPECT_NE(der_cert1, der_cert3);
+
+ // Synchronous completion.
+ // If we request RSA and EC, should now retrieve the EC cert.
+ SSLClientCertType type4;
+ types.insert(types.begin(), CLIENT_CERT_RSA_SIGN);
+ std::string private_key_info4, der_cert4;
+ error = service->GetOriginBoundCert(
+ origin, types, &type4, &private_key_info4, &der_cert4,
+ callback.callback(), &request_handle);
+ EXPECT_TRUE(request_handle == NULL);
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service->cert_count());
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type4);
+ EXPECT_EQ(private_key_info3, private_key_info4);
+ EXPECT_EQ(der_cert3, der_cert4);
+
+ EXPECT_EQ(4u, service->requests());
+ EXPECT_EQ(2u, service->cert_store_hits());
EXPECT_EQ(0u, service->inflight_joins());
}
+TEST(OriginBoundCertServiceTest, UnsupportedTypes) {
+ scoped_ptr<OriginBoundCertService> service(
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
+ std::string origin("https://encrypted.google.com:443");
+
+ int error;
+ std::vector<uint8> types;
+ TestCompletionCallback callback;
+ OriginBoundCertService::RequestHandle request_handle;
+
+ // Empty requested_types.
+ SSLClientCertType type1;
+ std::string private_key_info1, der_cert1;
+ error = service->GetOriginBoundCert(
+ origin, types, &type1, &private_key_info1, &der_cert1,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_INVALID_ARGUMENT, error);
+ EXPECT_TRUE(request_handle == NULL);
+
+ // No supported types in requested_types.
+ types.push_back(2);
+ types.push_back(3);
+ error = service->GetOriginBoundCert(
+ origin, types, &type1, &private_key_info1, &der_cert1,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_ORIGIN_BOUND_CERT_TYPE_UNSUPPORTED, error);
+ EXPECT_TRUE(request_handle == NULL);
+
+ // Supported types after unsupported ones in requested_types.
+ types.push_back(CLIENT_CERT_ECDSA_SIGN);
+ types.push_back(CLIENT_CERT_RSA_SIGN);
+ // Asynchronous completion.
+ EXPECT_EQ(0, service->cert_count());
+ error = service->GetOriginBoundCert(
+ origin, types, &type1, &private_key_info1, &der_cert1,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service->cert_count());
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1);
+ EXPECT_FALSE(private_key_info1.empty());
+ EXPECT_FALSE(der_cert1.empty());
+
+ // Now that the cert is created, doing requests for unsupported types
+ // shouldn't affect the created cert.
+ // Empty requested_types.
+ types.clear();
+ SSLClientCertType type2;
+ std::string private_key_info2, der_cert2;
+ error = service->GetOriginBoundCert(
+ origin, types, &type2, &private_key_info2, &der_cert2,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_INVALID_ARGUMENT, error);
+ EXPECT_TRUE(request_handle == NULL);
+
+ // No supported types in requested_types.
+ types.push_back(2);
+ types.push_back(3);
+ error = service->GetOriginBoundCert(
+ origin, types, &type2, &private_key_info2, &der_cert2,
+ callback.callback(), &request_handle);
+ EXPECT_EQ(ERR_ORIGIN_BOUND_CERT_TYPE_UNSUPPORTED, error);
+ EXPECT_TRUE(request_handle == NULL);
+
+ // If we request EC, the cert we created before should still be there.
+ types.push_back(CLIENT_CERT_RSA_SIGN);
+ types.push_back(CLIENT_CERT_ECDSA_SIGN);
+ error = service->GetOriginBoundCert(
+ origin, types, &type2, &private_key_info2, &der_cert2,
+ callback.callback(), &request_handle);
+ EXPECT_TRUE(request_handle == NULL);
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(1, service->cert_count());
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2);
+ EXPECT_EQ(private_key_info1, private_key_info2);
+ EXPECT_EQ(der_cert1, der_cert2);
+}
+
TEST(OriginBoundCertServiceTest, StoreCerts) {
scoped_ptr<OriginBoundCertService> service(
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_RSA_SIGN);
TestCompletionCallback callback;
OriginBoundCertService::RequestHandle request_handle;
std::string origin1("https://encrypted.google.com:443");
+ SSLClientCertType type1;
std::string private_key_info1, der_cert1;
EXPECT_EQ(0, service->cert_count());
error = service->GetOriginBoundCert(
- origin1, &private_key_info1, &der_cert1, callback.callback(),
- &request_handle);
+ origin1, types, &type1, &private_key_info1, &der_cert1,
+ callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle != NULL);
error = callback.WaitForResult();
@@ -87,10 +214,11 @@ TEST(OriginBoundCertServiceTest, StoreCerts) {
EXPECT_EQ(1, service->cert_count());
std::string origin2("https://www.verisign.com:443");
+ SSLClientCertType type2;
std::string private_key_info2, der_cert2;
error = service->GetOriginBoundCert(
- origin2, &private_key_info2, &der_cert2, callback.callback(),
- &request_handle);
+ origin2, types, &type2, &private_key_info2, &der_cert2,
+ callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle != NULL);
error = callback.WaitForResult();
@@ -98,10 +226,12 @@ TEST(OriginBoundCertServiceTest, StoreCerts) {
EXPECT_EQ(2, service->cert_count());
std::string origin3("https://www.twitter.com:443");
+ SSLClientCertType type3;
std::string private_key_info3, der_cert3;
+ types[0] = CLIENT_CERT_ECDSA_SIGN;
error = service->GetOriginBoundCert(
- origin3, &private_key_info3, &der_cert3, callback.callback(),
- &request_handle);
+ origin3, types, &type3, &private_key_info3, &der_cert3,
+ callback.callback(), &request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle != NULL);
error = callback.WaitForResult();
@@ -114,6 +244,9 @@ TEST(OriginBoundCertServiceTest, StoreCerts) {
EXPECT_NE(der_cert1, der_cert3);
EXPECT_NE(private_key_info2, private_key_info3);
EXPECT_NE(der_cert2, der_cert3);
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type1);
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type2);
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3);
}
// Tests an inflight join.
@@ -122,23 +255,30 @@ TEST(OriginBoundCertServiceTest, InflightJoin) {
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
std::string origin("https://encrypted.google.com:443");
int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_RSA_SIGN);
+ SSLClientCertType type1;
std::string private_key_info1, der_cert1;
TestCompletionCallback callback1;
OriginBoundCertService::RequestHandle request_handle1;
+ SSLClientCertType type2;
std::string private_key_info2, der_cert2;
TestCompletionCallback callback2;
OriginBoundCertService::RequestHandle request_handle2;
error = service->GetOriginBoundCert(
- origin, &private_key_info1, &der_cert1, callback1.callback(),
- &request_handle1);
+ origin, types, &type1, &private_key_info1, &der_cert1,
+ callback1.callback(), &request_handle1);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle1 != NULL);
+ // If we request EC and RSA in the 2nd request, should still join with the
+ // original request.
+ types.insert(types.begin(), CLIENT_CERT_ECDSA_SIGN);
error = service->GetOriginBoundCert(
- origin, &private_key_info2, &der_cert2, callback2.callback(),
- &request_handle2);
+ origin, types, &type2, &private_key_info2, &der_cert2,
+ callback2.callback(), &request_handle2);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle2 != NULL);
@@ -147,22 +287,73 @@ TEST(OriginBoundCertServiceTest, InflightJoin) {
error = callback2.WaitForResult();
EXPECT_EQ(OK, error);
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type1);
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type2);
EXPECT_EQ(2u, service->requests());
EXPECT_EQ(0u, service->cert_store_hits());
EXPECT_EQ(1u, service->inflight_joins());
}
-TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) {
+// Tests an inflight join with mismatching request types.
+TEST(OriginBoundCertServiceTest, InflightJoinTypeMismatch) {
scoped_ptr<OriginBoundCertService> service(
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
std::string origin("https://encrypted.google.com:443");
+ int error;
+ std::vector<uint8> types1;
+ types1.push_back(CLIENT_CERT_RSA_SIGN);
+ std::vector<uint8> types2;
+ types2.push_back(CLIENT_CERT_ECDSA_SIGN);
+
+ SSLClientCertType type1;
+ std::string private_key_info1, der_cert1;
+ TestCompletionCallback callback1;
+ OriginBoundCertService::RequestHandle request_handle1;
+
+ SSLClientCertType type2;
+ std::string private_key_info2, der_cert2;
+ TestCompletionCallback callback2;
+ OriginBoundCertService::RequestHandle request_handle2;
+
+ error = service->GetOriginBoundCert(
+ origin, types1, &type1, &private_key_info1, &der_cert1,
+ callback1.callback(), &request_handle1);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle1 != NULL);
+ // If we request only EC in the 2nd request, it should return an error.
+ error = service->GetOriginBoundCert(
+ origin, types2, &type2, &private_key_info2, &der_cert2,
+ callback2.callback(), &request_handle2);
+ EXPECT_EQ(ERR_ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH, error);
+ EXPECT_TRUE(request_handle2 == NULL);
+
+ error = callback1.WaitForResult();
+ EXPECT_EQ(OK, error);
+
+ EXPECT_FALSE(private_key_info1.empty());
+ EXPECT_FALSE(der_cert1.empty());
+ EXPECT_TRUE(private_key_info2.empty());
+ EXPECT_TRUE(der_cert2.empty());
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type1);
+ EXPECT_EQ(2u, service->requests());
+ EXPECT_EQ(0u, service->cert_store_hits());
+ EXPECT_EQ(0u, service->inflight_joins());
+}
+
+TEST(OriginBoundCertServiceTest, ExtractValuesFromBytesRSA) {
+ scoped_ptr<OriginBoundCertService> service(
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
+ std::string origin("https://encrypted.google.com:443");
+ SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_RSA_SIGN);
TestCompletionCallback callback;
OriginBoundCertService::RequestHandle request_handle;
error = service->GetOriginBoundCert(
- origin, &private_key_info, &der_cert, callback.callback(),
+ origin, types, &type, &private_key_info, &der_cert, callback.callback(),
&request_handle);
EXPECT_EQ(ERR_IO_PENDING, error);
EXPECT_TRUE(request_handle != NULL);
@@ -181,16 +372,60 @@ TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) {
EXPECT_TRUE(x509cert != NULL);
}
+TEST(OriginBoundCertServiceTest, ExtractValuesFromBytesEC) {
+ scoped_ptr<OriginBoundCertService> service(
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
+ std::string origin("https://encrypted.google.com:443");
+ SSLClientCertType type;
+ std::string private_key_info, der_cert;
+ int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_ECDSA_SIGN);
+ TestCompletionCallback callback;
+ OriginBoundCertService::RequestHandle request_handle;
+
+ error = service->GetOriginBoundCert(
+ origin, types, &type, &private_key_info, &der_cert, callback.callback(),
+ &request_handle);
+ EXPECT_EQ(ERR_IO_PENDING, error);
+ EXPECT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ EXPECT_EQ(OK, error);
+
+ base::StringPiece spki_piece;
+ ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert, &spki_piece));
+ std::vector<uint8> spki(
+ spki_piece.data(),
+ spki_piece.data() + spki_piece.size());
+
+ // Check that we can retrieve the key from the bytes.
+ std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end());
+ scoped_ptr<crypto::ECPrivateKey> private_key(
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+ OriginBoundCertService::kEPKIPassword, key_vec, spki));
+ EXPECT_TRUE(private_key != NULL);
+
+ // Check that we can retrieve the cert from the bytes.
+ scoped_refptr<X509Certificate> x509cert(
+ X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()));
+ EXPECT_TRUE(x509cert != NULL);
+}
+
// Tests that the callback of a canceled request is never made.
TEST(OriginBoundCertServiceTest, CancelRequest) {
scoped_ptr<OriginBoundCertService> service(
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
std::string origin("https://encrypted.google.com:443");
+ SSLClientCertType type;
std::string private_key_info, der_cert;
int error;
+ std::vector<uint8> types;
+ types.push_back(CLIENT_CERT_RSA_SIGN);
OriginBoundCertService::RequestHandle request_handle;
error = service->GetOriginBoundCert(origin,
+ types,
+ &type,
&private_key_info,
&der_cert,
base::Bind(&FailTest),
@@ -206,6 +441,8 @@ TEST(OriginBoundCertServiceTest, CancelRequest) {
for (int i = 0; i < 5; ++i) {
error = service->GetOriginBoundCert(
"https://encrypted.google.com:" + std::string(1, (char) ('1' + i)),
+ types,
+ &type,
&private_key_info,
&der_cert,
callback.callback(),
@@ -214,6 +451,10 @@ TEST(OriginBoundCertServiceTest, CancelRequest) {
EXPECT_TRUE(request_handle != NULL);
error = callback.WaitForResult();
}
+
+ // Even though the original request was cancelled, the service will still
+ // store the result, it just doesn't call the callback.
+ EXPECT_EQ(6, service->cert_count());
}
#endif // !defined(USE_OPENSSL)

Powered by Google App Engine
This is Rietveld 408576698