diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/net/base/keygen_handler_unittest.cc | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'chromium/net/base/keygen_handler_unittest.cc')
-rw-r--r-- | chromium/net/base/keygen_handler_unittest.cc | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/chromium/net/base/keygen_handler_unittest.cc b/chromium/net/base/keygen_handler_unittest.cc new file mode 100644 index 00000000000..5188d9d745c --- /dev/null +++ b/chromium/net/base/keygen_handler_unittest.cc @@ -0,0 +1,134 @@ +// Copyright (c) 2011 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 "net/base/keygen_handler.h" + +#include <string> + +#include "base/base64.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/threading/worker_pool.h" +#include "base/threading/thread_restrictions.h" +#include "base/synchronization/waitable_event.h" +#include "build/build_config.h" +#include "crypto/nss_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if defined(USE_NSS) +#include <private/pprthred.h> // PR_DetachThread +#endif + +namespace net { + +namespace { + +class KeygenHandlerTest : public ::testing::Test { + public: + KeygenHandlerTest() {} + virtual ~KeygenHandlerTest() {} + + virtual void SetUp() { +#if defined(OS_CHROMEOS) + crypto::OpenPersistentNSSDB(); +#endif + } +}; + +// Assert that |result| is a valid output for KeygenHandler given challenge +// string of |challenge|. +void AssertValidSignedPublicKeyAndChallenge(const std::string& result, + const std::string& challenge) { + ASSERT_GT(result.length(), 0U); + + // Verify it's valid base64: + std::string spkac; + ASSERT_TRUE(base::Base64Decode(result, &spkac)); + // In lieu of actually parsing and validating the DER data, + // just check that it exists and has a reasonable length. + // (It's almost always 590 bytes, but the DER encoding of the random key + // and signature could sometimes be a few bytes different.) + ASSERT_GE(spkac.length(), 200U); + ASSERT_LE(spkac.length(), 300U); + + // NOTE: + // The value of |result| can be validated by prefixing 'SPKAC=' to it + // and piping it through + // openssl spkac -verify + // whose output should look like: + // Netscape SPKI: + // Public Key Algorithm: rsaEncryption + // RSA Public Key: (2048 bit) + // Modulus (2048 bit): + // 00:b6:cc:14:c9:43:b5:2d:51:65:7e:11:8b:80:9e: ..... + // Exponent: 65537 (0x10001) + // Challenge String: some challenge + // Signature Algorithm: md5WithRSAEncryption + // 92:f3:cc:ff:0b:d3:d0:4a:3a:4c:ba:ff:d6:38:7f:a5:4b:b5: ..... + // Signature OK + // + // The value of |spkac| can be ASN.1-parsed with: + // openssl asn1parse -inform DER +} + +TEST_F(KeygenHandlerTest, SmokeTest) { + KeygenHandler handler(768, "some challenge", GURL("http://www.example.com")); + handler.set_stores_key(false); // Don't leave the key-pair behind + std::string result = handler.GenKeyAndSignChallenge(); + VLOG(1) << "KeygenHandler produced: " << result; + AssertValidSignedPublicKeyAndChallenge(result, "some challenge"); +} + +void ConcurrencyTestCallback(base::WaitableEvent* event, + const std::string& challenge, + std::string* result) { + // We allow Singleton use on the worker thread here since we use a + // WaitableEvent to synchronize, so it's safe. + base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton; + KeygenHandler handler(768, challenge, GURL("http://www.example.com")); + handler.set_stores_key(false); // Don't leave the key-pair behind. + *result = handler.GenKeyAndSignChallenge(); + event->Signal(); +#if defined(USE_NSS) + // Detach the thread from NSPR. + // Calling NSS functions attaches the thread to NSPR, which stores + // the NSPR thread ID in thread-specific data. + // The threads in our thread pool terminate after we have called + // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets + // segfaults on shutdown when the threads' thread-specific data + // destructors run. + PR_DetachThread(); +#endif +} + +// We asynchronously generate the keys so as not to hang up the IO thread. This +// test tries to catch concurrency problems in the keygen implementation. +TEST_F(KeygenHandlerTest, ConcurrencyTest) { + const int NUM_HANDLERS = 5; + base::WaitableEvent* events[NUM_HANDLERS] = { NULL }; + std::string results[NUM_HANDLERS]; + for (int i = 0; i < NUM_HANDLERS; i++) { + events[i] = new base::WaitableEvent(false, false); + base::WorkerPool::PostTask( + FROM_HERE, + base::Bind(ConcurrencyTestCallback, events[i], "some challenge", + &results[i]), + true); + } + + for (int i = 0; i < NUM_HANDLERS; i++) { + // Make sure the job completed + events[i]->Wait(); + delete events[i]; + events[i] = NULL; + + VLOG(1) << "KeygenHandler " << i << " produced: " << results[i]; + AssertValidSignedPublicKeyAndChallenge(results[i], "some challenge"); + } +} + +} // namespace + +} // namespace net |