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

Unified Diff: components/cronet/ios/test/cronet_test_base.mm

Issue 2928653002: [Cronet-iOS] Public-Key-Pinning Tests (Closed)
Patch Set: Fixed DEPS Created 3 years, 6 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
« no previous file with comments | « components/cronet/ios/test/cronet_test_base.h ('k') | components/cronet/ios/test/start_cronet.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/cronet/ios/test/cronet_test_base.mm
diff --git a/components/cronet/ios/test/cronet_test_base.mm b/components/cronet/ios/test/cronet_test_base.mm
new file mode 100644
index 0000000000000000000000000000000000000000..a056ab0bee5805a5ae28d767b9f37a2e92f539e0
--- /dev/null
+++ b/components/cronet/ios/test/cronet_test_base.mm
@@ -0,0 +1,188 @@
+// Copyright 2017 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 "cronet_test_base.h"
+
+#include "components/grpc_support/test/quic_test_server.h"
+#include "crypto/sha2.h"
+#include "net/base/net_errors.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/mock_cert_verifier.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+
+#pragma mark
+
+@implementation TestDelegate {
+ // Completion semaphore for this TestDelegate. When the request this delegate
+ // is attached to finishes (either successfully or with an error), this
+ // delegate signals this semaphore.
+ dispatch_semaphore_t _semaphore;
+}
+
+@synthesize error = _error;
+@synthesize totalBytesReceived = _totalBytesReceived;
+
+NSMutableArray<NSData*>* _responseData;
+
+- (id)init {
+ if (self = [super init]) {
+ _semaphore = dispatch_semaphore_create(0);
+ }
+ return self;
+}
+
+- (void)reset {
+ _responseData = nil;
+ _error = nil;
+ _totalBytesReceived = 0;
+}
+
+- (NSString*)responseBody {
+ if (_responseData == nil) {
+ return nil;
+ }
+ NSMutableString* body = [NSMutableString string];
+ for (NSData* data in _responseData) {
+ [body appendString:[[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding]];
+ }
+ VLOG(3) << "responseBody size:" << [body length]
+ << " chunks:" << [_responseData count];
+ return body;
+}
+
+- (BOOL)waitForDone {
+ int64_t deadline_ns = 20 * NSEC_PER_SEC;
+ return dispatch_semaphore_wait(
+ _semaphore, dispatch_time(DISPATCH_TIME_NOW, deadline_ns)) == 0;
+}
+
+- (void)URLSession:(NSURLSession*)session
+ didBecomeInvalidWithError:(NSError*)error {
+}
+
+- (void)URLSession:(NSURLSession*)session
+ task:(NSURLSessionTask*)task
+ didCompleteWithError:(NSError*)error {
+ [self setError:error];
+ dispatch_semaphore_signal(_semaphore);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ task:(NSURLSessionTask*)task
+ didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge
+ completionHandler:
+ (void (^)(NSURLSessionAuthChallengeDisposition disp,
+ NSURLCredential* credential))completionHandler {
+ completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ didReceiveResponse:(NSURLResponse*)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))
+ completionHandler {
+ completionHandler(NSURLSessionResponseAllow);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ didReceiveData:(NSData*)data {
+ _totalBytesReceived += [data length];
+ if (_responseData == nil) {
+ _responseData = [[NSMutableArray alloc] init];
+ }
+ [_responseData addObject:data];
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ willCacheResponse:(NSCachedURLResponse*)proposedResponse
+ completionHandler:
+ (void (^)(NSCachedURLResponse* cachedResponse))completionHandler {
+ completionHandler(proposedResponse);
+}
+
+@end
+
+namespace cronet {
+
+void CronetTestBase::SetUp() {
+ ::testing::Test::SetUp();
+ grpc_support::StartQuicTestServer();
+ delegate_ = [[TestDelegate alloc] init];
+}
+
+void CronetTestBase::TearDown() {
+ grpc_support::ShutdownQuicTestServer();
+ ::testing::Test::TearDown();
+}
+
+// Launches the supplied |task| and blocks until it completes, with a timeout
+// of 1 second.
+void CronetTestBase::StartDataTaskAndWaitForCompletion(
+ NSURLSessionDataTask* task) {
+ [delegate_ reset];
+ [task resume];
+ CHECK([delegate_ waitForDone]);
+}
+
+::testing::AssertionResult CronetTestBase::IsResponseSuccessful() {
+ if ([delegate_ error])
+ return ::testing::AssertionFailure() << "error in response: " <<
+ [[[delegate_ error] description]
+ cStringUsingEncoding:NSUTF8StringEncoding];
+ else
+ return ::testing::AssertionSuccess() << "no errors in response";
+}
+
+std::unique_ptr<net::MockCertVerifier> CronetTestBase::CreateMockCertVerifier(
+ const std::vector<std::string>& certs,
+ bool known_root) {
+ std::unique_ptr<net::MockCertVerifier> mock_cert_verifier(
+ new net::MockCertVerifier());
+ for (const auto& cert : certs) {
+ net::CertVerifyResult verify_result;
+ verify_result.verified_cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), cert);
+
+ // By default, HPKP verification is enabled for known trust roots only.
+ verify_result.is_issued_by_known_root = known_root;
+
+ // Calculate the public key hash and add it to the verify_result.
+ net::HashValue hashValue;
+ CHECK(CalculatePublicKeySha256(*verify_result.verified_cert.get(),
+ &hashValue));
+ verify_result.public_key_hashes.push_back(hashValue);
+
+ mock_cert_verifier->AddResultForCert(verify_result.verified_cert.get(),
+ verify_result, net::OK);
+ }
+ return mock_cert_verifier;
+}
+
+bool CronetTestBase::CalculatePublicKeySha256(const net::X509Certificate& cert,
+ net::HashValue* out_hash_value) {
+ // Convert the cert to DER encoded bytes.
+ std::string der_cert_bytes;
+ net::X509Certificate::OSCertHandle cert_handle = cert.os_cert_handle();
+ if (!net::X509Certificate::GetDEREncoded(cert_handle, &der_cert_bytes)) {
+ LOG(INFO) << "Unable to convert the given cert to DER encoding";
+ return false;
+ }
+ // Extract the public key from the cert.
+ base::StringPiece spki_bytes;
+ if (!net::asn1::ExtractSPKIFromDERCert(der_cert_bytes, &spki_bytes)) {
+ LOG(INFO) << "Unable to retrieve the public key from the DER cert";
+ return false;
+ }
+ // Calculate SHA256 hash of public key bytes.
+ out_hash_value->tag = net::HASH_VALUE_SHA256;
+ crypto::SHA256HashString(spki_bytes, out_hash_value->data(),
+ crypto::kSHA256Length);
+ return true;
+}
+
+} // namespace cronet
« no previous file with comments | « components/cronet/ios/test/cronet_test_base.h ('k') | components/cronet/ios/test/start_cronet.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698