summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-29 15:08:48 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-29 15:08:48 +0000
commit06256e5dee1d1aa8e5feebe3399634408914a66e (patch)
tree4f3398c7dd1a2020515579fcec6672e5a42d0b5e /net
parent5123b36099d7dfff857b2d170e8593f60b77df12 (diff)
downloadchromium_src-06256e5dee1d1aa8e5feebe3399634408914a66e.zip
chromium_src-06256e5dee1d1aa8e5feebe3399634408914a66e.tar.gz
chromium_src-06256e5dee1d1aa8e5feebe3399634408914a66e.tar.bz2
Decouples TransportSecurityState from NSS.
Adds support for TransportSecurityState to run on top of OpenSSL. BUG= TEST=TransportSecurityStateTest.* Review URL: http://codereview.chromium.org/8050021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/transport_security_state.cc123
-rw-r--r--net/base/transport_security_state_unittest.cc18
2 files changed, 109 insertions, 32 deletions
diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc
index 31454fd..a0e187b 100644
--- a/net/base/transport_security_state.cc
+++ b/net/base/transport_security_state.cc
@@ -4,12 +4,17 @@
#include "net/base/transport_security_state.h"
+#if defined(USE_OPENSSL)
+#include <openssl/ssl.h>
+#include <openssl/ecdsa.h>
+#else // !defined(USE_OPENSSL)
#include <nspr.h>
#include <cryptohi.h>
#include <hasht.h>
#include <keyhi.h>
#include <pk11pub.h>
+#endif
#include "base/base64.h"
#include "base/json/json_reader.h"
@@ -26,6 +31,10 @@
#include "googleurl/src/gurl.h"
#include "net/base/dns_util.h"
+#if defined(USE_OPENSSL)
+#include "crypto/openssl_util.h"
+#endif
+
namespace net {
const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year
@@ -394,6 +403,55 @@ static const uint8 kP256SubjectPublicKeyInfoPrefix[] = {
0x42, 0x00,
};
+// VerifySignature returns true iff |sig| is a valid signature of
+// |hash| by |pubkey|. The actual implementation is crypto library
+// specific.
+static bool VerifySignature(const base::StringPiece& pubkey,
+ const base::StringPiece& sig,
+ const base::StringPiece& hash);
+
+#if defined(USE_OPENSSL)
+
+static EVP_PKEY* DecodeX962P256PublicKey(
+ const base::StringPiece& pubkey_bytes) {
+ // The public key is an X9.62 encoded P256 point.
+ if (pubkey_bytes.size() != 1 + 2*32)
+ return NULL;
+
+ std::string pubkey_spki(
+ reinterpret_cast<const char*>(kP256SubjectPublicKeyInfoPrefix),
+ sizeof(kP256SubjectPublicKeyInfoPrefix));
+ pubkey_spki += pubkey_bytes.as_string();
+
+ EVP_PKEY* ret = NULL;
+ const unsigned char* der_pubkey =
+ reinterpret_cast<const unsigned char*>(pubkey_spki.data());
+ d2i_PUBKEY(&ret, &der_pubkey, pubkey_spki.size());
+ return ret;
+}
+
+static bool VerifySignature(const base::StringPiece& pubkey,
+ const base::StringPiece& sig,
+ const base::StringPiece& hash) {
+ crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> secpubkey(
+ DecodeX962P256PublicKey(pubkey));
+ if (!secpubkey.get())
+ return false;
+
+
+ crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(
+ EVP_PKEY_get1_EC_KEY(secpubkey.get()));
+ if (!ec_key.get())
+ return false;
+
+ return ECDSA_verify(0, reinterpret_cast<const unsigned char*>(hash.data()),
+ hash.size(),
+ reinterpret_cast<const unsigned char*>(sig.data()),
+ sig.size(), ec_key.get()) == 1;
+}
+
+#else
+
// DecodeX962P256PublicKey parses an uncompressed, X9.62 format, P256 elliptic
// curve point from |pubkey_bytes| and returns it as a SECKEYPublicKey.
static SECKEYPublicKey* DecodeX962P256PublicKey(
@@ -421,6 +479,41 @@ static SECKEYPublicKey* DecodeX962P256PublicKey(
return public_key;
}
+static bool VerifySignature(const base::StringPiece& pubkey,
+ const base::StringPiece& sig,
+ const base::StringPiece& hash) {
+ SECKEYPublicKey* secpubkey = DecodeX962P256PublicKey(pubkey);
+ if (!secpubkey)
+ return false;
+
+ SECItem sigitem;
+ memset(&sigitem, 0, sizeof(sigitem));
+ sigitem.data = reinterpret_cast<uint8*>(const_cast<char*>(sig.data()));
+ sigitem.len = sig.size();
+
+ // |decoded_sigitem| is newly allocated, as is the data that it points to.
+ SECItem* decoded_sigitem = DSAU_DecodeDerSigToLen(
+ &sigitem, SECKEY_SignatureLen(secpubkey));
+
+ if (!decoded_sigitem) {
+ SECKEY_DestroyPublicKey(secpubkey);
+ return false;
+ }
+
+ SECItem hashitem;
+ memset(&hashitem, 0, sizeof(hashitem));
+ hashitem.data = reinterpret_cast<unsigned char*>(
+ const_cast<char*>(hash.data()));
+ hashitem.len = hash.size();
+
+ SECStatus rv = PK11_Verify(secpubkey, decoded_sigitem, &hashitem, NULL);
+ SECKEY_DestroyPublicKey(secpubkey);
+ SECITEM_FreeItem(decoded_sigitem, PR_TRUE);
+ return rv == SECSuccess;
+}
+
+#endif // !defined(USE_OPENSSL)
+
// These are the tag values that we use. Tags are little-endian on the wire and
// these values correspond to the ASCII of the name.
static const uint32 kTagALGO = 0x4f474c41;
@@ -474,34 +567,10 @@ bool TransportSecurityState::ParseSidePin(
leaf_spki.as_string(), leaf_spki_hash, sizeof(leaf_spki_hash));
have_leaf_spki_hash = true;
}
- SECItem hashitem;
- memset(&hashitem, 0, sizeof(hashitem));
- hashitem.data = leaf_spki_hash;
- hashitem.len = sizeof(leaf_spki_hash);
-
- SECKEYPublicKey* secpubkey = DecodeX962P256PublicKey(pubkey);
- if (!secpubkey)
- continue;
-
- SECItem sigitem;
- memset(&sigitem, 0, sizeof(sigitem));
- sigitem.data = reinterpret_cast<uint8*>(const_cast<char*>(sig.data()));
- sigitem.len = sig.size();
-
- // |decoded_sigitem| is newly allocated, as is the data that it points to.
- SECItem* decoded_sigitem = DSAU_DecodeDerSigToLen(
- &sigitem, SECKEY_SignatureLen(secpubkey));
-
- if (!decoded_sigitem) {
- SECKEY_DestroyPublicKey(secpubkey);
- continue;
- }
-
- SECStatus rv = PK11_Verify(secpubkey, decoded_sigitem, &hashitem, NULL);
- SECKEY_DestroyPublicKey(secpubkey);
- SECITEM_FreeItem(decoded_sigitem, PR_TRUE);
- if (rv == SECSuccess) {
+ if (VerifySignature(pubkey, sig, base::StringPiece(
+ reinterpret_cast<const char*>(leaf_spki_hash),
+ sizeof(leaf_spki_hash)))) {
SHA1Fingerprint fpr;
base::SHA1HashBytes(
reinterpret_cast<const uint8*>(pubkey.data()),
diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc
index 11c6edf..3169025 100644
--- a/net/base/transport_security_state_unittest.cc
+++ b/net/base/transport_security_state_unittest.cc
@@ -3,13 +3,25 @@
// found in the LICENSE file.
#include "base/string_piece.h"
-#include "crypto/nss_util.h"
#include "net/base/transport_security_state.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(USE_OPENSSL)
+#include "crypto/openssl_util.h"
+#else
+#include "crypto/nss_util.h"
+#endif
+
namespace net {
class TransportSecurityStateTest : public testing::Test {
+ virtual void SetUp() {
+#if defined(USE_NSS)
+ crypto::EnsureNSSInit();
+#elif defined(USE_OPENSSL)
+ crypto::EnsureOpenSSLInit();
+#endif
+ }
};
TEST_F(TransportSecurityStateTest, BogusHeaders) {
@@ -909,7 +921,6 @@ static const uint8 kSidePinExpectedHash[20] = {
};
TEST_F(TransportSecurityStateTest, ParseSidePins) {
- crypto::EnsureNSSInit();
base::StringPiece leaf_spki(reinterpret_cast<const char*>(kSidePinLeafSPKI),
sizeof(kSidePinLeafSPKI));
@@ -925,7 +936,6 @@ TEST_F(TransportSecurityStateTest, ParseSidePins) {
}
TEST_F(TransportSecurityStateTest, ParseSidePinsFailsWithBadData) {
- crypto::EnsureNSSInit();
uint8 leaf_spki_copy[sizeof(kSidePinLeafSPKI)];
memcpy(leaf_spki_copy, kSidePinLeafSPKI, sizeof(leaf_spki_copy));
@@ -957,8 +967,6 @@ TEST_F(TransportSecurityStateTest, DISABLED_ParseSidePinsFuzz) {
// Disabled because it's too slow for normal tests. Run manually when
// changing the underlying code.
- crypto::EnsureNSSInit();
-
base::StringPiece leaf_spki(reinterpret_cast<const char*>(kSidePinLeafSPKI),
sizeof(kSidePinLeafSPKI));
uint8 side_info_copy[sizeof(kSidePinInfo)];