Import Cobalt 19.master.0.205881
diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn
new file mode 100644
index 0000000..f8c9ba8
--- /dev/null
+++ b/src/crypto/BUILD.gn
@@ -0,0 +1,222 @@
+# Copyright (c) 2013 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.
+
+import("//build/config/crypto.gni")
+import("//testing/test.gni")
+
+component("crypto") {
+  output_name = "crcrypto"  # Avoid colliding with OpenSSL's libcrypto.
+  sources = [
+    "aead.cc",
+    "aead.h",
+    "apple_keychain.h",
+    "apple_keychain_ios.mm",
+    "apple_keychain_mac.mm",
+    "capi_util.cc",
+    "capi_util.h",
+    "crypto_export.h",
+    "ec_private_key.cc",
+    "ec_private_key.h",
+    "ec_signature_creator.cc",
+    "ec_signature_creator.h",
+    "ec_signature_creator_impl.cc",
+    "ec_signature_creator_impl.h",
+    "encryptor.cc",
+    "encryptor.h",
+    "hkdf.cc",
+    "hkdf.h",
+    "hmac.cc",
+    "hmac.h",
+    "mac_security_services_lock.cc",
+    "mac_security_services_lock.h",
+
+    # TODO(brettw) these mocks should be moved to a test_support_crypto target
+    # if possible.
+    "mock_apple_keychain.cc",
+    "mock_apple_keychain.h",
+    "mock_apple_keychain_ios.cc",
+    "mock_apple_keychain_mac.cc",
+    "nss_crypto_module_delegate.h",
+    "nss_key_util.cc",
+    "nss_key_util.h",
+    "nss_util.cc",
+    "nss_util.h",
+    "nss_util_internal.h",
+    "openssl_util.cc",
+    "openssl_util.h",
+    "p224.cc",
+    "p224.h",
+    "p224_spake.cc",
+    "p224_spake.h",
+    "random.cc",
+    "random.h",
+    "rsa_private_key.cc",
+    "rsa_private_key.h",
+    "scoped_capi_types.h",
+    "scoped_nss_types.h",
+    "secure_hash.cc",
+    "secure_hash.h",
+    "secure_util.cc",
+    "secure_util.h",
+    "sha2.cc",
+    "sha2.h",
+    "signature_creator.cc",
+    "signature_creator.h",
+    "signature_verifier.cc",
+    "signature_verifier.h",
+    "symmetric_key.cc",
+    "symmetric_key.h",
+    "wincrypt_shim.h",
+  ]
+
+  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+  deps = [
+    ":platform",
+    "//base",
+    "//base/third_party/dynamic_annotations",
+  ]
+
+  public_deps = [
+    "//third_party/boringssl",
+  ]
+
+  if (!is_mac && !is_ios) {
+    sources -= [
+      "apple_keychain.h",
+      "mock_apple_keychain.cc",
+      "mock_apple_keychain.h",
+    ]
+  } else {
+    libs = [
+      "CoreFoundation.framework",
+      "Security.framework",
+    ]
+  }
+
+  if (!is_mac) {
+    sources -= [
+      "mac_security_services_lock.cc",
+      "mac_security_services_lock.h",
+    ]
+  }
+  if (!is_win) {
+    sources -= [
+      "capi_util.cc",
+      "capi_util.h",
+    ]
+  }
+
+  # Some files are built when NSS is used for the platform certificate library.
+  if (!use_nss_certs) {
+    sources -= [
+      "nss_key_util.cc",
+      "nss_key_util.h",
+      "nss_util.cc",
+      "nss_util.h",
+      "nss_util_internal.h",
+    ]
+  }
+
+  defines = [ "CRYPTO_IMPLEMENTATION" ]
+
+  if (is_nacl) {
+    deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
+  }
+}
+
+test("crypto_unittests") {
+  sources = [
+    "aead_unittest.cc",
+    "ec_private_key_unittest.cc",
+    "ec_signature_creator_unittest.cc",
+    "encryptor_unittest.cc",
+    "hmac_unittest.cc",
+    "nss_key_util_unittest.cc",
+    "nss_util_unittest.cc",
+    "p224_spake_unittest.cc",
+    "p224_unittest.cc",
+    "random_unittest.cc",
+    "rsa_private_key_unittest.cc",
+    "secure_hash_unittest.cc",
+    "sha2_unittest.cc",
+    "signature_creator_unittest.cc",
+    "signature_verifier_unittest.cc",
+    "symmetric_key_unittest.cc",
+  ]
+
+  # Some files are built when NSS is used for the platform certificate library.
+  if (!use_nss_certs) {
+    sources -= [
+      "nss_key_util_unittest.cc",
+      "nss_util_unittest.cc",
+    ]
+  }
+
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+  deps = [
+    ":crypto",
+    ":platform",
+    ":test_support",
+    "//base",
+    "//base/test:run_all_unittests",
+    "//base/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
+# This has no sources in some cases so can't be a static library.
+source_set("test_support") {
+  testonly = true
+  sources = []
+
+  if (use_nss_certs) {
+    sources += [
+      "scoped_test_nss_db.cc",
+      "scoped_test_nss_db.h",
+    ]
+  }
+
+  if (is_chromeos) {
+    sources += [
+      "scoped_test_nss_chromeos_user.cc",
+      "scoped_test_nss_chromeos_user.h",
+      "scoped_test_system_nss_key_slot.cc",
+      "scoped_test_system_nss_key_slot.h",
+    ]
+  }
+
+  deps = [
+    ":crypto",
+    ":platform",
+    "//base",
+  ]
+}
+
+config("platform_config") {
+  if (use_nss_certs && is_clang) {
+    # There is a broken header guard in /usr/include/nss/secmod.h:
+    # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
+    cflags = [ "-Wno-header-guard" ]
+  }
+}
+
+# This is a meta-target that forwards to NSS's SSL library or OpenSSL,
+# according to the state of the crypto flags. A target just wanting to depend
+# on the current SSL library should just depend on this.
+group("platform") {
+  public_deps = [
+    "//third_party/boringssl",
+  ]
+
+  # Link in NSS if it is used for the platform certificate library
+  # (use_nss_certs).
+  if (use_nss_certs) {
+    public_configs = [ ":platform_config" ]
+    public_configs += [ "//build/config/linux/nss:system_nss_no_ssl_config" ]
+  }
+}
diff --git a/src/crypto/aead.cc b/src/crypto/aead.cc
new file mode 100644
index 0000000..884ed15
--- /dev/null
+++ b/src/crypto/aead.cc
@@ -0,0 +1,127 @@
+// 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.h"
+
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/aes.h"
+#include "third_party/boringssl/src/include/openssl/evp.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;
+    case AES_256_GCM:
+      aead_ = EVP_aead_aes_256_gcm();
+      break;
+    case AES_256_GCM_SIV:
+      aead_ = EVP_aead_aes_256_gcm_siv();
+      break;
+  }
+}
+
+Aead::~Aead() = default;
+
+void Aead::Init(const std::string* key) {
+  DCHECK(!key_);
+  DCHECK_EQ(KeyLength(), key->size());
+  key_ = key;
+}
+
+bool Aead::Seal(base::StringPiece plaintext,
+                base::StringPiece nonce,
+                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_t*>(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_t* out_ptr = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&result, max_output_length + 1));
+
+  if (!EVP_AEAD_CTX_seal(
+          &ctx, out_ptr, &output_length, max_output_length,
+          reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+          reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(),
+          reinterpret_cast<const uint8_t*>(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(base::StringPiece ciphertext,
+                base::StringPiece nonce,
+                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_t*>(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_t* out_ptr = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&result, max_output_length + 1));
+
+  if (!EVP_AEAD_CTX_open(
+          &ctx, out_ptr, &output_length, max_output_length,
+          reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+          reinterpret_cast<const uint8_t*>(ciphertext.data()),
+          ciphertext.size(),
+          reinterpret_cast<const uint8_t*>(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 crypto
diff --git a/src/crypto/aead.h b/src/crypto/aead.h
new file mode 100644
index 0000000..810846c
--- /dev/null
+++ b/src/crypto/aead.h
@@ -0,0 +1,50 @@
+// 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 <string>
+
+#include "base/strings/string_piece.h"
+#include "crypto/crypto_export.h"
+#include "starboard/types.h"
+
+struct evp_aead_st;
+
+namespace crypto {
+
+// This class exposes the AES-128-CTR-HMAC-SHA256 and AES_256_GCM AEAD.
+class CRYPTO_EXPORT Aead {
+ public:
+  enum AeadAlgorithm { AES_128_CTR_HMAC_SHA256, AES_256_GCM, AES_256_GCM_SIV };
+
+  explicit Aead(AeadAlgorithm algorithm);
+
+  ~Aead();
+
+  void Init(const std::string* key);
+
+  bool Seal(base::StringPiece plaintext,
+            base::StringPiece nonce,
+            base::StringPiece additional_data,
+            std::string* ciphertext) const;
+
+  bool Open(base::StringPiece ciphertext,
+            base::StringPiece nonce,
+            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_AEAD_H_
diff --git a/src/crypto/aead_unittest.cc b/src/crypto/aead_unittest.cc
new file mode 100644
index 0000000..559e125
--- /dev/null
+++ b/src/crypto/aead_unittest.cc
@@ -0,0 +1,61 @@
+// 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.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const crypto::Aead::AeadAlgorithm kAllAlgorithms[]{
+    crypto::Aead::AES_128_CTR_HMAC_SHA256, crypto::Aead::AES_256_GCM,
+    crypto::Aead::AES_256_GCM_SIV,
+};
+
+class AeadTest : public testing::TestWithParam<crypto::Aead::AeadAlgorithm> {};
+
+INSTANTIATE_TEST_CASE_P(, AeadTest, testing::ValuesIn(kAllAlgorithms));
+
+TEST_P(AeadTest, SealOpen) {
+  crypto::Aead::AeadAlgorithm alg = GetParam();
+  crypto::Aead aead(alg);
+  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_P(AeadTest, SealOpenWrongKey) {
+  crypto::Aead::AeadAlgorithm alg = GetParam();
+  crypto::Aead aead(alg);
+  std::string key(aead.KeyLength(), 0);
+  std::string wrong_key(aead.KeyLength(), 1);
+  aead.Init(&key);
+  crypto::Aead aead_wrong_key(alg);
+  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());
+}
+
+}  // namespace
diff --git a/src/crypto/apple_keychain.h b/src/crypto/apple_keychain.h
new file mode 100644
index 0000000..778697f
--- /dev/null
+++ b/src/crypto/apple_keychain.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2012 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_APPLE_KEYCHAIN_H_
+#define CRYPTO_APPLE_KEYCHAIN_H_
+
+#include <Security/Security.h>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+#if defined(OS_IOS)
+using AppleSecKeychainItemRef = void*;
+#else
+using AppleSecKeychainItemRef = SecKeychainItemRef;
+#endif
+
+// Wraps the KeychainServices API in a very thin layer, to allow it to be
+// mocked out for testing.
+
+// See Keychain Services documentation for function documentation, as these call
+// through directly to their Keychain Services equivalents (Foo ->
+// SecKeychainFoo). The only exception is Free, which should be used for
+// anything returned from this class that would normally be freed with
+// CFRelease (to aid in testing).
+class CRYPTO_EXPORT AppleKeychain {
+ public:
+  AppleKeychain();
+  virtual ~AppleKeychain();
+
+  virtual OSStatus FindGenericPassword(UInt32 serviceNameLength,
+                                       const char* serviceName,
+                                       UInt32 accountNameLength,
+                                       const char* accountName,
+                                       UInt32* passwordLength,
+                                       void** passwordData,
+                                       AppleSecKeychainItemRef* itemRef) const;
+
+  virtual OSStatus ItemFreeContent(void* data) const;
+
+  virtual OSStatus AddGenericPassword(UInt32 serviceNameLength,
+                                      const char* serviceName,
+                                      UInt32 accountNameLength,
+                                      const char* accountName,
+                                      UInt32 passwordLength,
+                                      const void* passwordData,
+                                      AppleSecKeychainItemRef* itemRef) const;
+
+#if !defined(OS_IOS)
+  virtual OSStatus ItemDelete(AppleSecKeychainItemRef itemRef) const;
+#endif  // !defined(OS_IOS)
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AppleKeychain);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_APPLE_KEYCHAIN_H_
diff --git a/src/crypto/apple_keychain_ios.mm b/src/crypto/apple_keychain_ios.mm
new file mode 100644
index 0000000..e16407d
--- /dev/null
+++ b/src/crypto/apple_keychain_ios.mm
@@ -0,0 +1,195 @@
+// Copyright (c) 2012 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/apple_keychain.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsobject.h"
+
+namespace {
+
+enum KeychainAction {
+  kKeychainActionCreate,
+  kKeychainActionUpdate
+};
+
+// Creates a dictionary that can be used to query the keystore.
+// Ownership follows the Create rule.
+CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength,
+                                           const char* serviceName,
+                                           UInt32 accountNameLength,
+                                           const char* accountName) {
+  CFMutableDictionaryRef query =
+      CFDictionaryCreateMutable(NULL,
+                                5,
+                                &kCFTypeDictionaryKeyCallBacks,
+                                &kCFTypeDictionaryValueCallBacks);
+  // Type of element is generic password.
+  CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
+
+  // Set the service name.
+  base::scoped_nsobject<NSString> service_name_ns(
+      [[NSString alloc] initWithBytes:serviceName
+                               length:serviceNameLength
+                             encoding:NSUTF8StringEncoding]);
+  CFDictionarySetValue(query, kSecAttrService,
+                       base::mac::NSToCFCast(service_name_ns));
+
+  // Set the account name.
+  base::scoped_nsobject<NSString> account_name_ns(
+      [[NSString alloc] initWithBytes:accountName
+                               length:accountNameLength
+                             encoding:NSUTF8StringEncoding]);
+  CFDictionarySetValue(query, kSecAttrAccount,
+                       base::mac::NSToCFCast(account_name_ns));
+
+  // Use the proper search constants, return only the data of the first match.
+  CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
+  CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
+  return query;
+}
+
+// Creates a dictionary conatining the data to save into the keychain.
+// Ownership follows the Create rule.
+CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
+                                   const char* serviceName,
+                                   UInt32 accountNameLength,
+                                   const char* accountName,
+                                   UInt32 passwordLength,
+                                   const void* passwordData,
+                                   KeychainAction action) {
+  CFMutableDictionaryRef keychain_data =
+      CFDictionaryCreateMutable(NULL,
+                                0,
+                                &kCFTypeDictionaryKeyCallBacks,
+                                &kCFTypeDictionaryValueCallBacks);
+
+  // Set the password.
+  NSData* password = [NSData dataWithBytes:passwordData length:passwordLength];
+  CFDictionarySetValue(keychain_data, kSecValueData,
+                       base::mac::NSToCFCast(password));
+
+  // If this is not a creation, no structural information is needed.
+  if (action != kKeychainActionCreate)
+    return keychain_data;
+
+  // Set the type of the data.
+  CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword);
+
+  // Only allow access when the device has been unlocked.
+  CFDictionarySetValue(keychain_data,
+                       kSecAttrAccessible,
+                       kSecAttrAccessibleWhenUnlocked);
+
+  // Set the service name.
+  base::scoped_nsobject<NSString> service_name_ns(
+      [[NSString alloc] initWithBytes:serviceName
+                               length:serviceNameLength
+                             encoding:NSUTF8StringEncoding]);
+  CFDictionarySetValue(keychain_data, kSecAttrService,
+                       base::mac::NSToCFCast(service_name_ns));
+
+  // Set the account name.
+  base::scoped_nsobject<NSString> account_name_ns(
+      [[NSString alloc] initWithBytes:accountName
+                               length:accountNameLength
+                             encoding:NSUTF8StringEncoding]);
+  CFDictionarySetValue(keychain_data, kSecAttrAccount,
+                       base::mac::NSToCFCast(account_name_ns));
+
+  return keychain_data;
+}
+
+}  // namespace
+
+namespace crypto {
+
+AppleKeychain::AppleKeychain() {}
+
+AppleKeychain::~AppleKeychain() {}
+
+OSStatus AppleKeychain::ItemFreeContent(void* data) const {
+  free(data);
+  return noErr;
+}
+
+OSStatus AppleKeychain::AddGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32 passwordLength,
+    const void* passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  base::ScopedCFTypeRef<CFDictionaryRef> query(CreateGenericPasswordQuery(
+      serviceNameLength, serviceName, accountNameLength, accountName));
+  // Check that there is not already a password.
+  OSStatus status = SecItemCopyMatching(query, NULL);
+  if (status == errSecItemNotFound) {
+    // A new entry must be created.
+    base::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
+        CreateKeychainData(serviceNameLength,
+                           serviceName,
+                           accountNameLength,
+                           accountName,
+                           passwordLength,
+                           passwordData,
+                           kKeychainActionCreate));
+    status = SecItemAdd(keychain_data, NULL);
+  } else if (status == noErr) {
+    // The entry must be updated.
+    base::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
+        CreateKeychainData(serviceNameLength,
+                           serviceName,
+                           accountNameLength,
+                           accountName,
+                           passwordLength,
+                           passwordData,
+                           kKeychainActionUpdate));
+    status = SecItemUpdate(query, keychain_data);
+  }
+
+  return status;
+}
+
+OSStatus AppleKeychain::FindGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32* passwordLength,
+    void** passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  DCHECK((passwordData && passwordLength) ||
+         (!passwordData && !passwordLength));
+  base::ScopedCFTypeRef<CFDictionaryRef> query(CreateGenericPasswordQuery(
+      serviceNameLength, serviceName, accountNameLength, accountName));
+
+  // Get the keychain item containing the password.
+  CFTypeRef resultRef = NULL;
+  OSStatus status = SecItemCopyMatching(query, &resultRef);
+  base::ScopedCFTypeRef<CFTypeRef> result(resultRef);
+
+  if (status != noErr) {
+    if (passwordData) {
+      *passwordData = NULL;
+      *passwordLength = 0;
+    }
+    return status;
+  }
+
+  if (passwordData) {
+    CFDataRef data = base::mac::CFCast<CFDataRef>(result);
+    NSUInteger length = CFDataGetLength(data);
+    *passwordData = malloc(length * sizeof(UInt8));
+    CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData);
+    *passwordLength = length;
+  }
+  return status;
+}
+
+}  // namespace crypto
diff --git a/src/crypto/apple_keychain_mac.mm b/src/crypto/apple_keychain_mac.mm
new file mode 100644
index 0000000..5158f48
--- /dev/null
+++ b/src/crypto/apple_keychain_mac.mm
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 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/apple_keychain.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/synchronization/lock.h"
+#include "crypto/mac_security_services_lock.h"
+
+namespace crypto {
+
+AppleKeychain::AppleKeychain() {}
+
+AppleKeychain::~AppleKeychain() {}
+
+OSStatus AppleKeychain::ItemDelete(AppleSecKeychainItemRef itemRef) const {
+  base::AutoLock lock(GetMacSecurityServicesLock());
+  return SecKeychainItemDelete(itemRef);
+}
+
+OSStatus AppleKeychain::FindGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32* passwordLength,
+    void** passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  base::AutoLock lock(GetMacSecurityServicesLock());
+  return SecKeychainFindGenericPassword(nullptr, serviceNameLength, serviceName,
+                                        accountNameLength, accountName,
+                                        passwordLength, passwordData, itemRef);
+}
+
+OSStatus AppleKeychain::ItemFreeContent(void* data) const {
+  base::AutoLock lock(GetMacSecurityServicesLock());
+  return SecKeychainItemFreeContent(nullptr, data);
+}
+
+OSStatus AppleKeychain::AddGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32 passwordLength,
+    const void* passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  base::AutoLock lock(GetMacSecurityServicesLock());
+  return SecKeychainAddGenericPassword(nullptr, serviceNameLength, serviceName,
+                                       accountNameLength, accountName,
+                                       passwordLength, passwordData, itemRef);
+}
+
+}  // namespace crypto
diff --git a/src/crypto/capi_util.cc b/src/crypto/capi_util.cc
new file mode 100644
index 0000000..0182364
--- /dev/null
+++ b/src/crypto/capi_util.cc
@@ -0,0 +1,22 @@
+// 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 "crypto/capi_util.h"
+
+#include <stdlib.h>
+
+#include "starboard/memory.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+void* WINAPI CryptAlloc(size_t size) {
+  return SbMemoryAllocate(size);
+}
+
+void WINAPI CryptFree(void* p) {
+  SbMemoryFree(p);
+}
+
+}  // namespace crypto
diff --git a/src/crypto/capi_util.h b/src/crypto/capi_util.h
new file mode 100644
index 0000000..9064959
--- /dev/null
+++ b/src/crypto/capi_util.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 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_CAPI_UTIL_H_
+#define CRYPTO_CAPI_UTIL_H_
+
+#include <windows.h>
+
+#include "crypto/crypto_export.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+// Wrappers of malloc and free for CryptoAPI routines that need memory
+// allocators, such as in CRYPT_DECODE_PARA. Such routines require WINAPI
+// calling conventions.
+CRYPTO_EXPORT void* WINAPI CryptAlloc(size_t size);
+CRYPTO_EXPORT void WINAPI CryptFree(void* p);
+
+}  // namespace crypto
+
+#endif  // CRYPTO_CAPI_UTIL_H_
diff --git a/src/crypto/crypto.gyp b/src/crypto/crypto.gyp
index 3705097..354d689 100644
--- a/src/crypto/crypto.gyp
+++ b/src/crypto/crypto.gyp
@@ -8,10 +8,10 @@
       'type': '<(component)',
       'product_name': 'crcrypto',  # Avoid colliding with OpenSSL's libcrypto
       'dependencies': [
-        '../base/base.gyp:base',
-        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        '<(DEPTH)/starboard/starboard.gyp:starboard',
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '<(DEPTH)/third_party/boringssl/boringssl.gyp:crypto',
+        '<(DEPTH)/starboard/starboard.gyp:starboard',
       ],
       'defines': [
         'CRYPTO_IMPLEMENTATION',
@@ -20,22 +20,26 @@
         4018,
       ],
       'sources': [
+        'aead.cc',
+        'aead.h',
         'crypto_export.h',
-        'crypto_module_blocking_password_delegate.h',
+        'ec_private_key.cc',
         'ec_private_key.h',
-        'ec_private_key_openssl.cc',
         'ec_signature_creator.cc',
         'ec_signature_creator.h',
+        'ec_signature_creator_impl.cc',
         'ec_signature_creator_impl.h',
-        'ec_signature_creator_openssl.cc',
         'encryptor.cc',
         'encryptor.h',
-        'encryptor_openssl.cc',
-        'ghash.cc',
-        'ghash.h',
+        'hkdf.cc',
+        'hkdf.h',
         'hmac.cc',
         'hmac.h',
-        'hmac_openssl.cc',
+        'mac_security_services_lock.cc',
+        'mac_security_services_lock.h',
+
+        # TODO(brettw) these mocks should be moved to a test_support_crypto
+        # target if possible.
         'openssl_util.cc',
         'openssl_util.h',
         'p224.cc',
@@ -46,43 +50,32 @@
         'random.h',
         'rsa_private_key.cc',
         'rsa_private_key.h',
-        'rsa_private_key_ios.cc',
-        'rsa_private_key_mac.cc',
-        'rsa_private_key_openssl.cc',
-        'rsa_private_key_win.cc',
-        'scoped_capi_types.h',
-        'scoped_nss_types.h',
+        'secure_hash.cc',
         'secure_hash.h',
-        'secure_hash_openssl.cc',
         'secure_util.cc',
         'secure_util.h',
         'sha2.cc',
         'sha2.h',
+        'signature_creator.cc',
         'signature_creator.h',
-        'signature_creator_mac.cc',
-        'signature_creator_openssl.cc',
-        'signature_creator_win.cc',
+        'signature_verifier.cc',
         'signature_verifier.h',
-        'signature_verifier_openssl.cc',
+        'symmetric_key.cc',
         'symmetric_key.h',
-        'symmetric_key_openssl.cc',
+        'wincrypt_shim.h',
       ],
     },
     {
       'target_name': 'crypto_unittests',
       'type': '<(gtest_target_type)',
       'sources': [
-        # Infrastructure files.
-        'run_all_unittests.cc',
-
-        # Tests.
+        'aead_unittest.cc',
         'ec_private_key_unittest.cc',
         'ec_signature_creator_unittest.cc',
         'encryptor_unittest.cc',
-        'ghash_unittest.cc',
         'hmac_unittest.cc',
-        'p224_unittest.cc',
         'p224_spake_unittest.cc',
+        'p224_unittest.cc',
         'random_unittest.cc',
         'rsa_private_key_unittest.cc',
         'secure_hash_unittest.cc',
@@ -93,10 +86,11 @@
       ],
       'dependencies': [
         'crypto',
-        '../base/base.gyp:base',
-        '../base/base.gyp:test_support_base',
-        '../testing/gmock.gyp:gmock',
-        '../testing/gtest.gyp:gtest',
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/base/base.gyp:test_support_base',
+        '<(DEPTH)/base/base.gyp:run_all_unittests',
+        '<(DEPTH)/testing/gmock.gyp:gmock',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
       ],
     },
   ],
@@ -112,7 +106,7 @@
           'variables': {
             'executable_name': 'crypto_unittests',
           },
-          'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+          'includes': [ '../starboard/build/deploy.gypi' ],
         },
       ],
     }],
diff --git a/src/crypto/crypto_export.h b/src/crypto/crypto_export.h
index 6b1acc8..605af94 100644
--- a/src/crypto/crypto_export.h
+++ b/src/crypto/crypto_export.h
@@ -6,33 +6,27 @@
 #define CRYPTO_CRYPTO_EXPORT_H_
 
 // Defines CRYPTO_EXPORT so that functionality implemented by the crypto module
-// can be exported to consumers, and CRYPTO_EXPORT_PRIVATE that allows unit
-// tests to access features not intended to be used directly by real consumers.
+// can be exported to consumers.
 
 #if defined(COMPONENT_BUILD)
-#if defined(_MSC_VER)
+#if defined(WIN32)
 
 #if defined(CRYPTO_IMPLEMENTATION)
 #define CRYPTO_EXPORT __declspec(dllexport)
-#define CRYPTO_EXPORT_PRIVATE __declspec(dllexport)
 #else
 #define CRYPTO_EXPORT __declspec(dllimport)
-#define CRYPTO_EXPORT_PRIVATE __declspec(dllimport)
 #endif  // defined(CRYPTO_IMPLEMENTATION)
 
 #else  // defined(WIN32)
 #if defined(CRYPTO_IMPLEMENTATION)
 #define CRYPTO_EXPORT __attribute__((visibility("default")))
-#define CRYPTO_EXPORT_PRIVATE __attribute__((visibility("default")))
 #else
 #define CRYPTO_EXPORT
-#define CRYPTO_EXPORT_PRIVATE
 #endif
 #endif
 
 #else  // defined(COMPONENT_BUILD)
 #define CRYPTO_EXPORT
-#define CRYPTO_EXPORT_PRIVATE
 #endif
 
 #endif  // CRYPTO_CRYPTO_EXPORT_H_
diff --git a/src/crypto/crypto_module_blocking_password_delegate.h b/src/crypto/crypto_module_blocking_password_delegate.h
deleted file mode 100644
index c4acf1a..0000000
--- a/src/crypto/crypto_module_blocking_password_delegate.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 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_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
-#define CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
-
-#include <string>
-
-namespace crypto {
-
-// PK11_SetPasswordFunc is a global setting.  An implementation of
-// CryptoModuleBlockingPasswordDelegate should be passed as the user data
-// argument (|wincx|) to relevant NSS functions, which the global password
-// handler will call to do the actual work.
-class CryptoModuleBlockingPasswordDelegate {
- public:
-  virtual ~CryptoModuleBlockingPasswordDelegate() {}
-
-  // Requests a password to unlock |slot_name|. The interface is
-  // synchronous because NSS cannot issue an asynchronous
-  // request. |retry| is true if this is a request for the retry
-  // and we previously returned the wrong password.
-  // The implementation should set |*cancelled| to true if the user cancelled
-  // instead of entering a password, otherwise it should return the password the
-  // user entered.
-  virtual std::string RequestPassword(const std::string& slot_name, bool retry,
-                                      bool* cancelled) = 0;
-};
-
-}  // namespace crypto
-
-#endif  // CRYPTO_CRYPTO_MODULE_BLOCKING_PASSWORD_DELEGATE_H_
diff --git a/src/crypto/ec_private_key.cc b/src/crypto/ec_private_key.cc
new file mode 100644
index 0000000..11110ea
--- /dev/null
+++ b/src/crypto/ec_private_key.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2012 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/ec_private_key.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "crypto/openssl_util.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/bn.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
+#include "third_party/boringssl/src/include/openssl/pkcs8.h"
+
+namespace crypto {
+
+ECPrivateKey::~ECPrivateKey() = default;
+
+// static
+std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  bssl::UniquePtr<EC_KEY> ec_key(
+      EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+  if (!ec_key || !EC_KEY_generate_key(ec_key.get()))
+    return nullptr;
+
+  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
+  result->key_.reset(EVP_PKEY_new());
+  if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get()))
+    return nullptr;
+
+  CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get()));
+  return result;
+}
+
+// static
+std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
+    const std::vector<uint8_t>& input) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  CBS cbs;
+  CBS_init(&cbs, input.data(), input.size());
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
+  if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
+    return nullptr;
+
+  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
+  result->key_ = std::move(pkey);
+  return result;
+}
+
+// static
+std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+    const std::vector<uint8_t>& encrypted_private_key_info) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  CBS cbs;
+  CBS_init(&cbs, encrypted_private_key_info.data(),
+           encrypted_private_key_info.size());
+  bssl::UniquePtr<EVP_PKEY> pkey(
+      PKCS8_parse_encrypted_private_key(&cbs, "", 0));
+
+  // Hack for reading keys generated by an older version of the OpenSSL code.
+  // Some implementations encode the empty password as "\0\0" (passwords are
+  // normally encoded in big-endian UCS-2 with a NUL terminator) and some
+  // encode as the empty string. PKCS8_parse_encrypted_private_key
+  // distinguishes the two by whether the password is nullptr.
+  if (!pkey) {
+    CBS_init(&cbs, encrypted_private_key_info.data(),
+             encrypted_private_key_info.size());
+    pkey.reset(PKCS8_parse_encrypted_private_key(&cbs, nullptr, 0));
+  }
+
+  if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
+    return nullptr;
+
+  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
+  result->key_ = std::move(pkey);
+  return result;
+}
+
+std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const {
+  std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey());
+  copy->key_ = bssl::UpRef(key_);
+  return copy;
+}
+
+bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  uint8_t* der;
+  size_t der_len;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_private_key(cbb.get(), key_.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
+  return true;
+}
+
+bool ECPrivateKey::ExportEncryptedPrivateKey(
+    std::vector<uint8_t>* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  // Encrypt the object.
+  // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC
+  // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL
+  // equivalent.
+  uint8_t* der;
+  size_t der_len;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !PKCS8_marshal_encrypted_private_key(
+          cbb.get(), NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+          nullptr /* cipher */, nullptr /* no password */, 0 /* pass_len */,
+          nullptr /* salt */, 0 /* salt_len */, 1 /* iterations */,
+          key_.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
+  return true;
+}
+
+bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  uint8_t *der;
+  size_t der_len;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_public_key(cbb.get(), key_.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
+  return true;
+}
+
+bool ECPrivateKey::ExportRawPublicKey(std::string* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  // Export the x and y field elements as 32-byte, big-endian numbers. (This is
+  // the same as X9.62 uncompressed form without the leading 0x04 byte.)
+  EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_.get());
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  uint8_t buf[64];
+  if (!x || !y ||
+      !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
+                                           EC_KEY_get0_public_key(ec_key),
+                                           x.get(), y.get(), nullptr) ||
+      !BN_bn2bin_padded(buf, 32, x.get()) ||
+      !BN_bn2bin_padded(buf + 32, 32, y.get())) {
+    return false;
+  }
+
+  output->assign(reinterpret_cast<const char*>(buf), sizeof(buf));
+  return true;
+}
+
+ECPrivateKey::ECPrivateKey() = default;
+
+}  // namespace crypto
diff --git a/src/crypto/ec_private_key.h b/src/crypto/ec_private_key.h
index d3f5b73..f3a1cb7 100644
--- a/src/crypto/ec_private_key.h
+++ b/src/crypto/ec_private_key.h
@@ -5,22 +5,15 @@
 #ifndef CRYPTO_EC_PRIVATE_KEY_H_
 #define CRYPTO_EC_PRIVATE_KEY_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
-
-#if defined(USE_OPENSSL)
-// Forward declaration for openssl/*.h
-typedef struct evp_pkey_st EVP_PKEY;
-#else
-// Forward declaration.
-typedef struct CERTSubjectPublicKeyInfoStr CERTSubjectPublicKeyInfo;
-typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-#endif
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/base.h"
 
 namespace crypto {
 
@@ -33,106 +26,54 @@
  public:
   ~ECPrivateKey();
 
-  // Returns whether the system supports elliptic curve cryptography.
-  static bool IsSupported();
-
-  // Creates a new random instance. Can return NULL if initialization fails.
+  // Creates a new random instance. Can return nullptr if initialization fails.
   // The created key will use the NIST P-256 curve.
   // TODO(mattm): Add a curve parameter.
-  static ECPrivateKey* Create();
+  static std::unique_ptr<ECPrivateKey> Create();
 
-  // Creates a new random instance. Can return NULL if initialization fails.
-  // The created key is permanent and is not exportable in plaintext form.
-  //
-  // NOTE: Currently only available if USE_NSS is defined.
-  static ECPrivateKey* CreateSensitive();
+  // Create a new instance by importing an existing private key. The format is
+  // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return
+  // nullptr if initialization fails.
+  static std::unique_ptr<ECPrivateKey> CreateFromPrivateKeyInfo(
+      const std::vector<uint8_t>& input);
 
   // Creates a new instance by importing an existing key pair.
   // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo
-  // block and an X.509 SubjectPublicKeyInfo block.
-  // Returns NULL if initialization fails.
-  static ECPrivateKey* CreateFromEncryptedPrivateKeyInfo(
-      const std::string& password,
-      const std::vector<uint8>& encrypted_private_key_info,
-      const std::vector<uint8>& subject_public_key_info);
-
-  // Creates a new instance by importing an existing key pair.
-  // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo
-  // block and an X.509 SubjectPublicKeyInfo block.
-  // This can return NULL if initialization fails.  The created key is permanent
-  // and is not exportable in plaintext form.
+  // block with empty password and an X.509 SubjectPublicKeyInfo block.
+  // Returns nullptr if initialization fails.
   //
-  // NOTE: Currently only available if USE_NSS is defined.
-  static ECPrivateKey* CreateSensitiveFromEncryptedPrivateKeyInfo(
-      const std::string& password,
-      const std::vector<uint8>& encrypted_private_key_info,
-      const std::vector<uint8>& subject_public_key_info);
+  // This function is deprecated. Use CreateFromPrivateKeyInfo for new code.
+  // See https://crbug.com/603319.
+  static std::unique_ptr<ECPrivateKey> CreateFromEncryptedPrivateKeyInfo(
+      const std::vector<uint8_t>& encrypted_private_key_info);
 
-#if !defined(USE_OPENSSL)
-  // Imports the key pair and returns in |public_key| and |key|.
-  // Shortcut for code that needs to keep a reference directly to NSS types
-  // without having to create a ECPrivateKey object and make a copy of them.
-  // TODO(mattm): move this function to some NSS util file.
-  static bool ImportFromEncryptedPrivateKeyInfo(
-      const std::string& password,
-      const uint8* encrypted_private_key_info,
-      size_t encrypted_private_key_info_len,
-      CERTSubjectPublicKeyInfo* decoded_spki,
-      bool permanent,
-      bool sensitive,
-      SECKEYPrivateKey** key,
-      SECKEYPublicKey** public_key);
-#endif
+  // Returns a copy of the object.
+  std::unique_ptr<ECPrivateKey> Copy() const;
 
-#if defined(USE_OPENSSL)
-  EVP_PKEY* key() { return key_; }
-#else
-  SECKEYPrivateKey* key() { return key_; }
-  SECKEYPublicKey* public_key() { return public_key_; }
-#endif
+  EVP_PKEY* key() { return key_.get(); }
+
+  // Exports the private key to a PKCS #8 PrivateKeyInfo block.
+  bool ExportPrivateKey(std::vector<uint8_t>* output) const;
 
   // Exports the private key as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo
-  // block and the public key as an X.509 SubjectPublicKeyInfo block.
-  // The |password| and |iterations| are used as inputs to the key derivation
-  // function for generating the encryption key.  PKCS #5 recommends a minimum
-  // of 1000 iterations, on modern systems a larger value may be preferrable.
-  bool ExportEncryptedPrivateKey(const std::string& password,
-                                 int iterations,
-                                 std::vector<uint8>* output);
+  // block wth empty password. This was historically used as a workaround for
+  // NSS API deficiencies and does not provide security.
+  //
+  // This function is deprecated. Use ExportPrivateKey for new code. See
+  // https://crbug.com/603319.
+  bool ExportEncryptedPrivateKey(std::vector<uint8_t>* output) const;
 
   // Exports the public key to an X.509 SubjectPublicKeyInfo block.
-  bool ExportPublicKey(std::vector<uint8>* output);
+  bool ExportPublicKey(std::vector<uint8_t>* output) const;
 
-  // Exports private key data for testing. The format of data stored into output
-  // doesn't matter other than that it is consistent for the same key.
-  bool ExportValue(std::vector<uint8>* output);
-  bool ExportECParams(std::vector<uint8>* output);
+  // Exports the public key as an EC point in the uncompressed point format.
+  bool ExportRawPublicKey(std::string* output) const;
 
  private:
   // Constructor is private. Use one of the Create*() methods above instead.
   ECPrivateKey();
 
-  // Shared helper for Create() and CreateSensitive().
-  // TODO(cmasone): consider replacing |permanent| and |sensitive| with a
-  //                flags arg created by ORing together some enumerated values.
-  static ECPrivateKey* CreateWithParams(bool permanent,
-                                        bool sensitive);
-
-  // Shared helper for CreateFromEncryptedPrivateKeyInfo() and
-  // CreateSensitiveFromEncryptedPrivateKeyInfo().
-  static ECPrivateKey* CreateFromEncryptedPrivateKeyInfoWithParams(
-      const std::string& password,
-      const std::vector<uint8>& encrypted_private_key_info,
-      const std::vector<uint8>& subject_public_key_info,
-      bool permanent,
-      bool sensitive);
-
-#if defined(USE_OPENSSL)
-  EVP_PKEY* key_;
-#else
-  SECKEYPrivateKey* key_;
-  SECKEYPublicKey* public_key_;
-#endif
+  bssl::UniquePtr<EVP_PKEY> key_;
 
   DISALLOW_COPY_AND_ASSIGN(ECPrivateKey);
 };
diff --git a/src/crypto/ec_private_key_openssl.cc b/src/crypto/ec_private_key_openssl.cc
deleted file mode 100644
index 20214e6..0000000
--- a/src/crypto/ec_private_key_openssl.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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/ec_private_key.h"
-
-#include "base/logging.h"
-
-namespace crypto {
-
-ECPrivateKey::~ECPrivateKey() {}
-
-// static
-bool ECPrivateKey::IsSupported() {
-  return false;
-}
-
-// static
-ECPrivateKey* ECPrivateKey::Create() {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-ECPrivateKey* ECPrivateKey::CreateSensitive() {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-    const std::string& password,
-    const std::vector<uint8>& encrypted_private_key_info,
-    const std::vector<uint8>& subject_public_key_info) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-ECPrivateKey* ECPrivateKey::CreateSensitiveFromEncryptedPrivateKeyInfo(
-    const std::string& password,
-    const std::vector<uint8>& encrypted_private_key_info,
-    const std::vector<uint8>& subject_public_key_info) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-bool ECPrivateKey::ExportEncryptedPrivateKey(
-    const std::string& password,
-    int iterations,
-    std::vector<uint8>* output) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool ECPrivateKey::ExportPublicKey(std::vector<uint8>* output) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool ECPrivateKey::ExportValue(std::vector<uint8>* output) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/ec_private_key_unittest.cc b/src/crypto/ec_private_key_unittest.cc
index a052a9a..aa7e774 100644
--- a/src/crypto/ec_private_key_unittest.cc
+++ b/src/crypto/ec_private_key_unittest.cc
@@ -4,104 +4,318 @@
 
 #include "crypto/ec_private_key.h"
 
+#include <memory>
 #include <vector>
 
-#include "base/memory/scoped_ptr.h"
+#include "base/macros.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_OPENSSL)
-// Once ECPrivateKey is implemented for OpenSSL, remove this #if block.
-// TODO(mattm): When that happens, also add some exported keys from each to test
-// interop between NSS and OpenSSL.
-TEST(ECPrivateKeyUnitTest, OpenSSLStub) {
-  scoped_ptr<crypto::ECPrivateKey> keypair1(
-      crypto::ECPrivateKey::Create());
-  ASSERT_FALSE(keypair1.get());
-}
-#else
-// Generate random private keys. Export, then re-import. We should get
-// back the same exact public key, and the private key should have the same
-// value and elliptic curve params.
-TEST(ECPrivateKeyUnitTest, InitRandomTest) {
-  const std::string password1 = "";
-  const std::string password2 = "test";
+namespace {
 
-  scoped_ptr<crypto::ECPrivateKey> keypair1(
-      crypto::ECPrivateKey::Create());
-  scoped_ptr<crypto::ECPrivateKey> keypair2(
-      crypto::ECPrivateKey::Create());
-  ASSERT_TRUE(keypair1.get());
-  ASSERT_TRUE(keypair2.get());
+void ExpectKeysEqual(const crypto::ECPrivateKey* keypair1,
+                     const crypto::ECPrivateKey* keypair2) {
+  std::vector<uint8_t> privkey1;
+  std::vector<uint8_t> privkey2;
+  EXPECT_TRUE(keypair1->ExportPrivateKey(&privkey1));
+  EXPECT_TRUE(keypair2->ExportPrivateKey(&privkey2));
+  EXPECT_EQ(privkey1, privkey2);
 
-  std::vector<uint8> key1value;
-  std::vector<uint8> key2value;
-  std::vector<uint8> key1params;
-  std::vector<uint8> key2params;
-  EXPECT_TRUE(keypair1->ExportValue(&key1value));
-  EXPECT_TRUE(keypair2->ExportValue(&key2value));
-  EXPECT_TRUE(keypair1->ExportECParams(&key1params));
-  EXPECT_TRUE(keypair2->ExportECParams(&key2params));
-
-  std::vector<uint8> privkey1;
-  std::vector<uint8> privkey2;
-  std::vector<uint8> pubkey1;
-  std::vector<uint8> pubkey2;
-  ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey(
-      password1, 1, &privkey1));
-  ASSERT_TRUE(keypair2->ExportEncryptedPrivateKey(
-      password2, 1, &privkey2));
+  std::vector<uint8_t> pubkey1;
+  std::vector<uint8_t> pubkey2;
   EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1));
   EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2));
+  EXPECT_EQ(pubkey1, pubkey2);
 
-  scoped_ptr<crypto::ECPrivateKey> keypair3(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-          password1, privkey1, pubkey1));
-  scoped_ptr<crypto::ECPrivateKey> keypair4(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-          password2, privkey2, pubkey2));
-  ASSERT_TRUE(keypair3.get());
-  ASSERT_TRUE(keypair4.get());
-
-  std::vector<uint8> key3value;
-  std::vector<uint8> key4value;
-  std::vector<uint8> key3params;
-  std::vector<uint8> key4params;
-  EXPECT_TRUE(keypair3->ExportValue(&key3value));
-  EXPECT_TRUE(keypair4->ExportValue(&key4value));
-  EXPECT_TRUE(keypair3->ExportECParams(&key3params));
-  EXPECT_TRUE(keypair4->ExportECParams(&key4params));
-
-  EXPECT_EQ(key1value, key3value);
-  EXPECT_EQ(key2value, key4value);
-  EXPECT_EQ(key1params, key3params);
-  EXPECT_EQ(key2params, key4params);
-
-  std::vector<uint8> pubkey3;
-  std::vector<uint8> pubkey4;
-  EXPECT_TRUE(keypair3->ExportPublicKey(&pubkey3));
-  EXPECT_TRUE(keypair4->ExportPublicKey(&pubkey4));
-
-  EXPECT_EQ(pubkey1, pubkey3);
-  EXPECT_EQ(pubkey2, pubkey4);
+  std::string raw_pubkey1;
+  std::string raw_pubkey2;
+  EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1));
+  EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2));
+  EXPECT_EQ(raw_pubkey1, raw_pubkey2);
 }
 
-TEST(ECPrivateKeyUnitTest, BadPasswordTest) {
-  const std::string password1 = "";
-  const std::string password2 = "test";
+}  // namespace
 
-  scoped_ptr<crypto::ECPrivateKey> keypair1(
+// Generate random private keys. Export, then re-import in several ways. We
+// should get back the same exact public key, and the private key should have
+// the same value and elliptic curve params.
+TEST(ECPrivateKeyUnitTest, InitRandomTest) {
+  std::unique_ptr<crypto::ECPrivateKey> keypair(crypto::ECPrivateKey::Create());
+  ASSERT_TRUE(keypair);
+
+  // Re-import as a PrivateKeyInfo.
+  std::vector<uint8_t> privkey;
+  EXPECT_TRUE(keypair->ExportPrivateKey(&privkey));
+  std::unique_ptr<crypto::ECPrivateKey> keypair_copy =
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(privkey);
+  ASSERT_TRUE(keypair_copy);
+  ExpectKeysEqual(keypair.get(), keypair_copy.get());
+
+  // Re-import as an EncryptedPrivateKeyInfo with kPassword1.
+  std::vector<uint8_t> encrypted_privkey;
+  EXPECT_TRUE(keypair->ExportEncryptedPrivateKey(&encrypted_privkey));
+  keypair_copy = crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+      encrypted_privkey);
+  ASSERT_TRUE(keypair_copy);
+  ExpectKeysEqual(keypair.get(), keypair_copy.get());
+}
+
+TEST(ECPrivateKeyUnitTest, Copy) {
+  std::unique_ptr<crypto::ECPrivateKey> keypair1(
       crypto::ECPrivateKey::Create());
-  ASSERT_TRUE(keypair1.get());
+  std::unique_ptr<crypto::ECPrivateKey> keypair2(keypair1->Copy());
+  ASSERT_TRUE(keypair1);
+  ASSERT_TRUE(keypair2);
 
-  std::vector<uint8> privkey1;
-  std::vector<uint8> pubkey1;
-  ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey(
-      password1, 1, &privkey1));
-  ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1));
-
-  scoped_ptr<crypto::ECPrivateKey> keypair2(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-          password2, privkey1, pubkey1));
-  ASSERT_FALSE(keypair2.get());
+  ExpectKeysEqual(keypair1.get(), keypair2.get());
 }
-#endif  // !defined(USE_OPENSSL)
+
+TEST(ECPrivateKeyUnitTest, CreateFromPrivateKeyInfo) {
+  static const uint8_t kPrivateKeyInfo[] = {
+      0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+      0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+      0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+      0x07, 0x0f, 0x08, 0x72, 0x7a, 0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9,
+      0x4d, 0x89, 0x68, 0x77, 0x08, 0xb5, 0x6f, 0xc9, 0x5d, 0x30, 0x77, 0x0e,
+      0xe8, 0xd1, 0xc9, 0xce, 0x0a, 0x8b, 0xb4, 0x6a, 0xa1, 0x44, 0x03, 0x42,
+      0x00, 0x04, 0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f,
+      0x1e, 0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d,
+      0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7,
+      0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2,
+      0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94,
+      0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1,
+  };
+  static const uint8_t kSubjectPublicKeyInfo[] = {
+      0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+      0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+      0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe,
+      0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e,
+      0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01,
+      0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56,
+      0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1,
+      0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1,
+  };
+  static const uint8_t kRawPublicKey[] = {
+      0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e,
+      0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d,
+      0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01,
+      0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3, 0x1e,
+      0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5, 0x1d,
+      0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1,
+  };
+
+  std::unique_ptr<crypto::ECPrivateKey> key =
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(std::vector<uint8_t>(
+          std::begin(kPrivateKeyInfo), std::end(kPrivateKeyInfo)));
+  ASSERT_TRUE(key);
+
+  std::vector<uint8_t> public_key;
+  ASSERT_TRUE(key->ExportPublicKey(&public_key));
+  EXPECT_EQ(std::vector<uint8_t>(std::begin(kSubjectPublicKeyInfo),
+                                 std::end(kSubjectPublicKeyInfo)),
+            public_key);
+
+  std::string raw_public_key;
+  ASSERT_TRUE(key->ExportRawPublicKey(&raw_public_key));
+  EXPECT_EQ(std::string(reinterpret_cast<const char*>(kRawPublicKey),
+                        sizeof(kRawPublicKey)),
+            raw_public_key);
+}
+
+TEST(ECPrivateKeyUnitTest, RSAPrivateKeyInfo) {
+  static const uint8_t kPrivateKeyInfo[] = {
+      0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+      0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+      0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+      0x00, 0xb8, 0x7f, 0x2b, 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
+      0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, 0x55, 0x84, 0xd5, 0x3a,
+      0xbf, 0x2b, 0xa4, 0x64, 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
+      0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, 0xb0, 0x40, 0x53, 0x3a,
+      0xd7, 0x66, 0x09, 0x0f, 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
+      0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, 0xde, 0x4e, 0xb9, 0x57,
+      0x5e, 0x7e, 0x0a, 0xe5, 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
+      0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, 0x84, 0x32, 0x33, 0xf3,
+      0x17, 0x49, 0xbf, 0xe9, 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
+      0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, 0x53, 0x56, 0xa6, 0x83,
+      0xa2, 0xce, 0x93, 0x93, 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
+      0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, 0x37, 0xcb, 0xf2, 0x98,
+      0xa0, 0xce, 0xb4, 0xcb, 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7,
+      0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, 0xed, 0xb8, 0x48, 0x8b,
+      0x16, 0x93, 0x36, 0x95, 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6,
+      0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, 0x43, 0x78, 0xf9, 0xfe,
+      0x1f, 0x33, 0x23, 0x1e, 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b,
+      0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, 0x86, 0xb2, 0xcb, 0x3c,
+      0xfe, 0x4e, 0xa1, 0xfa, 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38,
+      0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, 0xa3, 0xf6, 0x85, 0x6b,
+      0x84, 0x43, 0xc9, 0x1e, 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e,
+      0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, 0x29, 0x5c, 0xc0, 0x4f,
+      0x01, 0x02, 0x41, 0x00, 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c,
+      0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, 0xcc, 0x61, 0xcd, 0x38,
+      0x42, 0x20, 0xd3, 0x82, 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89,
+      0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, 0xba, 0x16, 0x1a, 0xea,
+      0x15, 0xc6, 0xf0, 0xb8, 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2,
+      0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, 0x02, 0x41, 0x00, 0xc0,
+      0x60, 0x62, 0x80, 0xe1, 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72,
+      0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, 0x7d, 0xd6, 0xb8, 0x31,
+      0x2b, 0x84, 0x7f, 0x62, 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c,
+      0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, 0x5c, 0x09, 0x3c, 0xcf,
+      0x2f, 0x44, 0x9d, 0xb6, 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b,
+      0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, 0xe2, 0x0e, 0x56, 0xca,
+      0x03, 0x1a, 0xc0, 0xf9, 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda,
+      0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, 0xda, 0x55, 0x98, 0x74,
+      0xfc, 0x28, 0x17, 0x93, 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae,
+      0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, 0xb8, 0x06, 0x03, 0xba,
+      0x08, 0x59, 0x2b, 0x17, 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41,
+      0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, 0xa0, 0x24, 0xf5, 0xdb,
+      0x2f, 0xf0, 0x2f, 0xf1, 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0,
+      0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, 0xb4, 0x14, 0xd4, 0x09,
+      0x91, 0x33, 0x5a, 0xfd, 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69,
+      0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, 0xff, 0x6e, 0xeb, 0xc6,
+      0x86, 0xf5, 0xb4, 0xc7, 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f,
+      0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, 0x3e, 0x70, 0x8a, 0xbf,
+      0x27, 0x49, 0xb0, 0x99, 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6,
+      0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, 0xc6, 0xa4, 0x92, 0xd1,
+      0xce, 0x6c, 0x72, 0xfb, 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca,
+      0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, 0xb1, 0xc5, 0x15, 0xf3,
+  };
+
+  std::unique_ptr<crypto::ECPrivateKey> key =
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(std::vector<uint8_t>(
+          std::begin(kPrivateKeyInfo), std::end(kPrivateKeyInfo)));
+  EXPECT_FALSE(key);
+}
+
+TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) {
+  static const uint8_t kNSSKey[] = {
+      0x30, 0x81, 0xb8, 0x30, 0x23, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+      0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x15, 0x04, 0x10, 0x3f, 0xac, 0xe9,
+      0x38, 0xdb, 0x40, 0x6b, 0x26, 0x89, 0x09, 0x73, 0x18, 0x8d, 0x7f, 0x1c,
+      0x82, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0x5e, 0x5e, 0x11, 0xef, 0xbb,
+      0x7c, 0x4d, 0xec, 0xc0, 0xdc, 0xc7, 0x23, 0xd2, 0xc4, 0x77, 0xbc, 0xf4,
+      0x5d, 0x59, 0x4c, 0x07, 0xc2, 0x8a, 0x26, 0xfa, 0x25, 0x1c, 0xaa, 0x42,
+      0xed, 0xd0, 0xed, 0xbb, 0x5c, 0xe9, 0x13, 0x07, 0xaa, 0xdd, 0x52, 0x3c,
+      0x65, 0x25, 0xbf, 0x94, 0x02, 0xaf, 0xd6, 0x97, 0xe9, 0x33, 0x00, 0x76,
+      0x64, 0x4a, 0x73, 0xab, 0xfb, 0x99, 0x6e, 0x83, 0x12, 0x05, 0x86, 0x72,
+      0x6c, 0xd5, 0xa4, 0xcf, 0xb1, 0xd5, 0x4d, 0x54, 0x87, 0x8b, 0x4b, 0x95,
+      0x1d, 0xcd, 0xf3, 0xfe, 0xa8, 0xda, 0xe0, 0xb6, 0x72, 0x13, 0x3f, 0x2e,
+      0x66, 0xe0, 0xb9, 0x2e, 0xfa, 0x69, 0x40, 0xbe, 0xd7, 0x67, 0x6e, 0x53,
+      0x2b, 0x3f, 0x53, 0xe5, 0x39, 0x54, 0x77, 0xe1, 0x1d, 0xe6, 0x81, 0x92,
+      0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79,
+      0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0,
+      0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca,
+  };
+
+  std::unique_ptr<crypto::ECPrivateKey> keypair_nss(
+      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+          std::vector<uint8_t>(std::begin(kNSSKey), std::end(kNSSKey))));
+
+  EXPECT_TRUE(keypair_nss);
+}
+
+TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) {
+  static const uint8_t kOpenSSLKey[] = {
+      0x30, 0x81, 0xb0, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+      0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0xb2, 0xfe, 0x68,
+      0xc2, 0xea, 0x0f, 0x10, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0xe2,
+      0xf6, 0x1c, 0xca, 0xad, 0x64, 0x30, 0xbf, 0x88, 0x04, 0x35, 0xe5, 0x0f,
+      0x11, 0x49, 0x06, 0x01, 0x14, 0x33, 0x80, 0xa2, 0x78, 0x44, 0x5b, 0xaa,
+      0x0d, 0xd7, 0x00, 0x36, 0x9d, 0x91, 0x97, 0x37, 0x20, 0x7b, 0x27, 0xc1,
+      0xa0, 0xa2, 0x73, 0x06, 0x15, 0xdf, 0xc8, 0x13, 0x9b, 0xc9, 0x8c, 0x9c,
+      0xce, 0x00, 0xd0, 0xc8, 0x42, 0xc1, 0xda, 0x2b, 0x07, 0x2b, 0x12, 0xa3,
+      0xce, 0x10, 0x39, 0x7a, 0xf1, 0x55, 0x69, 0x8d, 0xa5, 0xc4, 0x2a, 0x00,
+      0x0d, 0x94, 0xc6, 0xde, 0x6a, 0x3d, 0xb7, 0xe5, 0x6d, 0x59, 0x3e, 0x09,
+      0xb5, 0xe3, 0x3e, 0xfc, 0x50, 0x56, 0xe9, 0x50, 0x42, 0x7c, 0xe7, 0xf0,
+      0x19, 0xbd, 0x31, 0xa7, 0x85, 0x47, 0xb3, 0xe9, 0xb3, 0x50, 0x3c, 0xc9,
+      0x32, 0x37, 0x1a, 0x93, 0x78, 0x48, 0x78, 0x82, 0xde, 0xad, 0x5c, 0xf2,
+      0xcf, 0xf2, 0xbb, 0x2c, 0x44, 0x05, 0x7f, 0x4a, 0xf9, 0xb1, 0x2b, 0xdd,
+      0x49, 0xf6, 0x7e, 0xd0, 0x42, 0xaa, 0x14, 0x3c, 0x24, 0x77, 0xb4,
+  };
+  static const uint8_t kOpenSSLPublicKey[] = {
+      0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+      0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+      0x42, 0x00, 0x04, 0xb9, 0xda, 0x0d, 0x71, 0x60, 0xb3, 0x63, 0x28, 0x22,
+      0x67, 0xe7, 0xe0, 0xa3, 0xf8, 0x00, 0x8e, 0x4c, 0x89, 0xed, 0x31, 0x34,
+      0xf6, 0xdb, 0xc4, 0xfe, 0x0b, 0x5d, 0xe1, 0x11, 0x39, 0x49, 0xa6, 0x50,
+      0xa8, 0xe3, 0x4a, 0xc0, 0x40, 0x88, 0xb8, 0x38, 0x3f, 0x56, 0xfb, 0x33,
+      0x8d, 0xd4, 0x64, 0x91, 0xd6, 0x15, 0x77, 0x42, 0x27, 0xc5, 0xaa, 0x44,
+      0xff, 0xab, 0x4d, 0xb5, 0x7e, 0x25, 0x3d,
+  };
+  static const uint8_t kOpenSSLRawPublicKey[] = {
+      0xb9, 0xda, 0x0d, 0x71, 0x60, 0xb3, 0x63, 0x28, 0x22, 0x67, 0xe7,
+      0xe0, 0xa3, 0xf8, 0x00, 0x8e, 0x4c, 0x89, 0xed, 0x31, 0x34, 0xf6,
+      0xdb, 0xc4, 0xfe, 0x0b, 0x5d, 0xe1, 0x11, 0x39, 0x49, 0xa6, 0x50,
+      0xa8, 0xe3, 0x4a, 0xc0, 0x40, 0x88, 0xb8, 0x38, 0x3f, 0x56, 0xfb,
+      0x33, 0x8d, 0xd4, 0x64, 0x91, 0xd6, 0x15, 0x77, 0x42, 0x27, 0xc5,
+      0xaa, 0x44, 0xff, 0xab, 0x4d, 0xb5, 0x7e, 0x25, 0x3d,
+  };
+
+  std::unique_ptr<crypto::ECPrivateKey> keypair_openssl(
+      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+          std::vector<uint8_t>(std::begin(kOpenSSLKey),
+                               std::end(kOpenSSLKey))));
+
+  EXPECT_TRUE(keypair_openssl);
+
+  std::vector<uint8_t> public_key;
+  EXPECT_TRUE(keypair_openssl->ExportPublicKey(&public_key));
+  EXPECT_EQ(std::vector<uint8_t>(std::begin(kOpenSSLPublicKey),
+                                 std::end(kOpenSSLPublicKey)),
+            public_key);
+
+  std::string raw_public_key;
+  EXPECT_TRUE(keypair_openssl->ExportRawPublicKey(&raw_public_key));
+  EXPECT_EQ(std::string(reinterpret_cast<const char*>(kOpenSSLRawPublicKey),
+                        arraysize(kOpenSSLRawPublicKey)),
+            raw_public_key);
+}
+
+// The Android code writes out Channel IDs differently from the NSS
+// implementation; the empty password is converted to "\0\0". The OpenSSL port
+// should support either.
+TEST(ECPrivateKeyUnitTest, LoadOldOpenSSLKeyTest) {
+  static const uint8_t kOpenSSLKey[] = {
+      0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86,
+      0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa,
+      0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01,
+      0x80, 0xcb, 0x2a, 0x14, 0xaa, 0x4f, 0x38, 0x4c, 0xe1, 0x49, 0x00, 0xe2,
+      0x1a, 0x3a, 0x75, 0x87, 0x7e, 0x3d, 0xea, 0x4d, 0x53, 0xd4, 0x46, 0x47,
+      0x23, 0x8f, 0xa1, 0x72, 0x51, 0x92, 0x86, 0x8b, 0xeb, 0x53, 0xe6, 0x6a,
+      0x0a, 0x6b, 0xb6, 0xa0, 0xdc, 0x0f, 0xdc, 0x20, 0xc3, 0x45, 0x85, 0xf1,
+      0x95, 0x90, 0x5c, 0xf4, 0xfa, 0xee, 0x47, 0xaf, 0x35, 0xd0, 0xd0, 0xd3,
+      0x14, 0xde, 0x0d, 0xca, 0x1b, 0xd3, 0xbb, 0x20, 0xec, 0x9d, 0x6a, 0xd4,
+      0xc1, 0xce, 0x60, 0x81, 0xab, 0x0c, 0x72, 0x10, 0xfa, 0x28, 0x3c, 0xac,
+      0x87, 0x7b, 0x82, 0x85, 0x00, 0xb8, 0x58, 0x9c, 0x07, 0xc4, 0x7d, 0xa9,
+      0xc5, 0x94, 0x95, 0xf7, 0x23, 0x93, 0x3f, 0xed, 0xef, 0x92, 0x55, 0x25,
+      0x74, 0xbb, 0xd3, 0xd1, 0x67, 0x3b, 0x3d, 0x5a, 0xfe, 0x84, 0xf8, 0x97,
+      0x7d, 0x7c, 0x01, 0xc7, 0xd7, 0x0d, 0xf8, 0xc3, 0x6d, 0xd6, 0xf1, 0xaa,
+      0x9d, 0x1f, 0x69, 0x97, 0x45, 0x06, 0xc4, 0x1c, 0x95, 0x3c, 0xe0, 0xef,
+      0x11, 0xb2, 0xb3, 0x72, 0x91, 0x9e, 0x7d, 0x0f, 0x7f, 0xc8, 0xf6, 0x64,
+      0x49, 0x5e, 0x3c, 0x53, 0x37, 0x79, 0x03, 0x1c, 0x3f, 0x29, 0x6c, 0x6b,
+      0xea, 0x4c, 0x35, 0x9b, 0x6d, 0x1b, 0x59, 0x43, 0x4c, 0x14, 0x47, 0x2a,
+      0x36, 0x39, 0x2a, 0xd8, 0x96, 0x90, 0xdc, 0xfc, 0xd2, 0xdd, 0x23, 0x0e,
+      0x2c, 0xb3, 0x83, 0xf9, 0xf2, 0xe3, 0xe6, 0x99, 0x53, 0x57, 0x33, 0xc5,
+      0x5f, 0xf9, 0xfd, 0x56, 0x0b, 0x32, 0xd4, 0xf3, 0x9d, 0x5b, 0x34, 0xe5,
+      0x94, 0xbf, 0xb6, 0xc0, 0xce, 0xe1, 0x73, 0x5c, 0x02, 0x7a, 0x4c, 0xed,
+      0xde, 0x23, 0x38, 0x89, 0x9f, 0xcd, 0x51, 0xf3, 0x90, 0x80, 0xd3, 0x4b,
+      0x83, 0xd3, 0xee, 0xf2, 0x9e, 0x35, 0x91, 0xa5, 0xa3, 0xc0, 0x5c, 0xce,
+      0xdb, 0xaa, 0x70, 0x1e, 0x1d, 0xc1, 0x44, 0xea, 0x3b, 0xa7, 0x5a, 0x11,
+      0xd1, 0xf3, 0xf3, 0xd0, 0xf4, 0x5a, 0xc4, 0x99, 0xaf, 0x8d, 0xe2, 0xbc,
+      0xa2, 0xb9, 0x3d, 0x86, 0x5e, 0xba, 0xa0, 0xdf, 0x78, 0x81, 0x7c, 0x54,
+      0x31, 0xe3, 0x98, 0xb5, 0x46, 0xcb, 0x4d, 0x26, 0x4b, 0xf8, 0xac, 0x3a,
+      0x54, 0x1b, 0x77, 0x5a, 0x18, 0xa5, 0x43, 0x0e, 0x14, 0xde, 0x7b, 0xb7,
+      0x4e, 0x45, 0x99, 0x03, 0xd1, 0x3d, 0x18, 0xb2, 0x36, 0x00, 0x48, 0x07,
+      0x72, 0xbb, 0x4f, 0x21, 0x25, 0x3e, 0xda, 0x25, 0x24, 0x5b, 0xc8, 0xa0,
+      0x28, 0xd5, 0x9b, 0x96, 0x87, 0x07, 0x77, 0x84, 0xff, 0xd7, 0xac, 0x71,
+      0xf6, 0x61, 0x63, 0x0b, 0xfb, 0x42, 0xfd, 0x52, 0xf4, 0xc4, 0x35, 0x0c,
+      0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11,
+      0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16,
+      0xed,
+  };
+
+  std::unique_ptr<crypto::ECPrivateKey> keypair_openssl(
+      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+          std::vector<uint8_t>(std::begin(kOpenSSLKey),
+                               std::end(kOpenSSLKey))));
+
+  EXPECT_TRUE(keypair_openssl);
+}
diff --git a/src/crypto/ec_signature_creator.cc b/src/crypto/ec_signature_creator.cc
index a6887bc..339a81a 100644
--- a/src/crypto/ec_signature_creator.cc
+++ b/src/crypto/ec_signature_creator.cc
@@ -5,21 +5,23 @@
 #include "crypto/ec_signature_creator.h"
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "crypto/ec_signature_creator_impl.h"
 
 namespace crypto {
 
 namespace {
 
-ECSignatureCreatorFactory* g_factory_ = NULL;
+ECSignatureCreatorFactory* g_factory_ = nullptr;
 
 }  // namespace
 
 // static
-ECSignatureCreator* ECSignatureCreator::Create(ECPrivateKey* key) {
+std::unique_ptr<ECSignatureCreator> ECSignatureCreator::Create(
+    ECPrivateKey* key) {
   if (g_factory_)
     return g_factory_->Create(key);
-  return new ECSignatureCreatorImpl(key);
+  return std::make_unique<ECSignatureCreatorImpl>(key);
 }
 
 // static
diff --git a/src/crypto/ec_signature_creator.h b/src/crypto/ec_signature_creator.h
index 16e64f5..632bd3c 100644
--- a/src/crypto/ec_signature_creator.h
+++ b/src/crypto/ec_signature_creator.h
@@ -5,11 +5,12 @@
 #ifndef CRYPTO_EC_SIGNATURE_CREATOR_H_
 #define CRYPTO_EC_SIGNATURE_CREATOR_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -20,7 +21,7 @@
  public:
   virtual ~ECSignatureCreatorFactory() {}
 
-  virtual ECSignatureCreator* Create(ECPrivateKey* key) = 0;
+  virtual std::unique_ptr<ECSignatureCreator> Create(ECPrivateKey* key) = 0;
 };
 
 // Signs data using a bare private key (as opposed to a full certificate).
@@ -34,7 +35,7 @@
   // instance outlives the created ECSignatureCreator.
   // TODO(rch):  This is currently hard coded to use SHA256. Ideally, we should
   // pass in the hash algorithm identifier.
-  static ECSignatureCreator* Create(ECPrivateKey* key);
+  static std::unique_ptr<ECSignatureCreator> Create(ECPrivateKey* key);
 
   // Set a factory to make the Create function return non-standard
   // ECSignatureCreator objects.  Because the ECDSA algorithm involves
@@ -48,17 +49,17 @@
   //  ECDSA-Sig-Value ::= SEQUENCE {
   //    r     INTEGER,
   //    s     INTEGER }
-  virtual bool Sign(const uint8* data,
+  virtual bool Sign(const uint8_t* data,
                     int data_len,
-                    std::vector<uint8>* signature) = 0;
+                    std::vector<uint8_t>* signature) = 0;
 
   // DecodeSignature converts from a DER encoded ECDSA-Sig-Value (as produced
   // by Sign) to a `raw' ECDSA signature which consists of a pair of
   // big-endian, zero-padded, 256-bit integers, r and s. On success it returns
   // true and puts the raw signature into |out_raw_sig|.
   // (Only P-256 signatures are supported.)
-  virtual bool DecodeSignature(const std::vector<uint8>& signature,
-                               std::vector<uint8>* out_raw_sig) = 0;
+  virtual bool DecodeSignature(const std::vector<uint8_t>& signature,
+                               std::vector<uint8_t>* out_raw_sig) = 0;
 };
 
 }  // namespace crypto
diff --git a/src/crypto/ec_signature_creator_impl.cc b/src/crypto/ec_signature_creator_impl.cc
new file mode 100644
index 0000000..1aa26a6
--- /dev/null
+++ b/src/crypto/ec_signature_creator_impl.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 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/ec_signature_creator_impl.h"
+
+#include "base/logging.h"
+#include "crypto/ec_private_key.h"
+#include "crypto/openssl_util.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/bn.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ecdsa.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
+
+namespace crypto {
+
+ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key)
+    : key_(key) {
+  EnsureOpenSSLInit();
+}
+
+ECSignatureCreatorImpl::~ECSignatureCreatorImpl() = default;
+
+bool ECSignatureCreatorImpl::Sign(const uint8_t* data,
+                                  int data_len,
+                                  std::vector<uint8_t>* signature) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  bssl::ScopedEVP_MD_CTX ctx;
+  size_t sig_len = 0;
+  if (!ctx.get() ||
+      !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr,
+                          key_->key()) ||
+      !EVP_DigestSignUpdate(ctx.get(), data, data_len) ||
+      !EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len)) {
+    return false;
+  }
+
+  signature->resize(sig_len);
+  if (!EVP_DigestSignFinal(ctx.get(), &signature->front(), &sig_len))
+    return false;
+
+  // NOTE: A call to EVP_DigestSignFinal() with a nullptr second parameter
+  // returns a maximum allocation size, while the call without a nullptr
+  // returns the real one, which may be smaller.
+  signature->resize(sig_len);
+  return true;
+}
+
+bool ECSignatureCreatorImpl::DecodeSignature(
+    const std::vector<uint8_t>& der_sig,
+    std::vector<uint8_t>* out_raw_sig) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  // Create ECDSA_SIG object from DER-encoded data.
+  bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(
+      ECDSA_SIG_from_bytes(der_sig.data(), der_sig.size()));
+  if (!ecdsa_sig.get())
+    return false;
+
+  // The result is made of two 32-byte vectors.
+  const size_t kMaxBytesPerBN = 32;
+  std::vector<uint8_t> result(2 * kMaxBytesPerBN);
+
+  if (!BN_bn2bin_padded(&result[0], kMaxBytesPerBN, ecdsa_sig->r) ||
+      !BN_bn2bin_padded(&result[kMaxBytesPerBN], kMaxBytesPerBN,
+                        ecdsa_sig->s)) {
+    return false;
+  }
+  out_raw_sig->swap(result);
+  return true;
+}
+
+}  // namespace crypto
diff --git a/src/crypto/ec_signature_creator_impl.h b/src/crypto/ec_signature_creator_impl.h
index f2ef9d6..26d58cf 100644
--- a/src/crypto/ec_signature_creator_impl.h
+++ b/src/crypto/ec_signature_creator_impl.h
@@ -5,26 +5,29 @@
 #ifndef CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_
 #define CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_
 
+#include <vector>
+
 #include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "crypto/ec_signature_creator.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
 class ECSignatureCreatorImpl : public ECSignatureCreator {
  public:
   explicit ECSignatureCreatorImpl(ECPrivateKey* key);
-  virtual ~ECSignatureCreatorImpl();
+  ~ECSignatureCreatorImpl() override;
 
-  virtual bool Sign(const uint8* data,
-                    int data_len,
-                    std::vector<uint8>* signature) override;
+  bool Sign(const uint8_t* data,
+            int data_len,
+            std::vector<uint8_t>* signature) override;
 
-  virtual bool DecodeSignature(const std::vector<uint8>& der_sig,
-                               std::vector<uint8>* out_raw_sig) override;
+  bool DecodeSignature(const std::vector<uint8_t>& der_sig,
+                       std::vector<uint8_t>* out_raw_sig) override;
 
  private:
   ECPrivateKey* key_;
-  size_t signature_len_;
 
   DISALLOW_COPY_AND_ASSIGN(ECSignatureCreatorImpl);
 };
diff --git a/src/crypto/ec_signature_creator_openssl.cc b/src/crypto/ec_signature_creator_openssl.cc
deleted file mode 100644
index 8854f5e..0000000
--- a/src/crypto/ec_signature_creator_openssl.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 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/ec_signature_creator_impl.h"
-
-#include "base/logging.h"
-
-namespace crypto {
-
-ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key)
-    : key_(key) {
-  NOTIMPLEMENTED();
-}
-
-ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {}
-
-bool ECSignatureCreatorImpl::Sign(const uint8* data,
-                                  int data_len,
-                                  std::vector<uint8>* signature) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool ECSignatureCreatorImpl::DecodeSignature(const std::vector<uint8>& der_sig,
-                                             std::vector<uint8>* out_raw_sig) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/ec_signature_creator_unittest.cc b/src/crypto/ec_signature_creator_unittest.cc
index 9489e3a..f322ae1 100644
--- a/src/crypto/ec_signature_creator_unittest.cc
+++ b/src/crypto/ec_signature_creator_unittest.cc
@@ -4,62 +4,48 @@
 
 #include "crypto/ec_signature_creator.h"
 
+#include <memory>
 #include <string>
 #include <vector>
 
-#include "base/memory/scoped_ptr.h"
 #include "crypto/ec_private_key.h"
 #include "crypto/signature_verifier.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_OPENSSL)
-// Once ECSignatureCreator is implemented for OpenSSL, remove this #if block.
-// TODO(rch): When that happens, also add some exported keys from each to
+// TODO(rch): Add some exported keys from each to
 // test interop between NSS and OpenSSL.
-TEST(ECSignatureCreatorTest, OpenSSLStub) {
-  scoped_ptr<crypto::ECSignatureCreator> signer(
-      crypto::ECSignatureCreator::Create(NULL));
-  ASSERT_TRUE(signer.get());
-  EXPECT_FALSE(signer->Sign(NULL, 0, NULL));
-}
-#else
+
 TEST(ECSignatureCreatorTest, BasicTest) {
   // Do a verify round trip.
-  scoped_ptr<crypto::ECPrivateKey> key_original(
+  std::unique_ptr<crypto::ECPrivateKey> key_original(
       crypto::ECPrivateKey::Create());
-  ASSERT_TRUE(key_original.get());
+  ASSERT_TRUE(key_original);
 
-  std::vector<uint8> key_info;
-  ASSERT_TRUE(key_original->ExportEncryptedPrivateKey("", 1000, &key_info));
-  std::vector<uint8> pubkey_info;
-  ASSERT_TRUE(key_original->ExportPublicKey(&pubkey_info));
+  std::vector<uint8_t> key_info;
+  ASSERT_TRUE(key_original->ExportPrivateKey(&key_info));
 
-  scoped_ptr<crypto::ECPrivateKey> key(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo("", key_info,
-                                                              pubkey_info));
-  ASSERT_TRUE(key.get());
-  ASSERT_TRUE(key->key() != NULL);
+  std::unique_ptr<crypto::ECPrivateKey> key(
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(key->key());
 
-  scoped_ptr<crypto::ECSignatureCreator> signer(
+  std::unique_ptr<crypto::ECSignatureCreator> signer(
       crypto::ECSignatureCreator::Create(key.get()));
-  ASSERT_TRUE(signer.get());
+  ASSERT_TRUE(signer);
 
   std::string data("Hello, World!");
-  std::vector<uint8> signature;
-  ASSERT_TRUE(signer->Sign(reinterpret_cast<const uint8*>(data.c_str()),
-                           data.size(),
-                           &signature));
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(signer->Sign(reinterpret_cast<const uint8_t*>(data.c_str()),
+                           data.size(), &signature));
 
-  std::vector<uint8> public_key_info;
+  std::vector<uint8_t> public_key_info;
   ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
 
   crypto::SignatureVerifier verifier;
-  ASSERT_TRUE(verifier.VerifyInit(
-      crypto::SignatureVerifier::ECDSA_SHA256, &signature[0], signature.size(),
-      &public_key_info.front(), public_key_info.size()));
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256,
+                                  signature, public_key_info));
 
-  verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
-                        data.size());
+  verifier.VerifyUpdate(base::as_bytes(base::make_span(data)));
   ASSERT_TRUE(verifier.VerifyFinal());
 }
-#endif  // !defined(USE_OPENSSL)
diff --git a/src/crypto/encryptor.cc b/src/crypto/encryptor.cc
index a673f81..390f287 100644
--- a/src/crypto/encryptor.cc
+++ b/src/crypto/encryptor.cc
@@ -5,24 +5,60 @@
 #include "crypto/encryptor.h"
 
 #include "base/logging.h"
+#include "base/strings/string_util.h"
 #include "base/sys_byteorder.h"
+#include "crypto/openssl_util.h"
+#include "crypto/symmetric_key.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/aes.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
 
 namespace crypto {
 
+namespace {
+
+const EVP_CIPHER* GetCipherForKey(const SymmetricKey* key) {
+  switch (key->key().length()) {
+    case 16: return EVP_aes_128_cbc();
+    case 32: return EVP_aes_256_cbc();
+    default:
+      return nullptr;
+  }
+}
+
+// On destruction this class will cleanup the ctx, and also clear the OpenSSL
+// ERR stack as a convenience.
+class ScopedCipherCTX {
+ public:
+  ScopedCipherCTX() {
+    EVP_CIPHER_CTX_init(&ctx_);
+  }
+  ~ScopedCipherCTX() {
+    EVP_CIPHER_CTX_cleanup(&ctx_);
+    ClearOpenSSLERRStack(FROM_HERE);
+  }
+  EVP_CIPHER_CTX* get() { return &ctx_; }
+
+ private:
+  EVP_CIPHER_CTX ctx_;
+};
+
+}  // namespace
+
 /////////////////////////////////////////////////////////////////////////////
 // Encyptor::Counter Implementation.
-Encryptor::Counter::Counter(const base::StringPiece& counter) {
+Encryptor::Counter::Counter(base::StringPiece counter) {
   CHECK(sizeof(counter_) == counter.length());
 
-  memcpy(&counter_, counter.data(), sizeof(counter_));
+  SbMemoryCopy(&counter_, counter.data(), sizeof(counter_));
 }
 
-Encryptor::Counter::~Counter() {
-}
+Encryptor::Counter::~Counter() = default;
 
 bool Encryptor::Counter::Increment() {
-  uint64 low_num = base::NetToHost64(counter_.components64[1]);
-  uint64 new_low_num = low_num + 1;
+  uint64_t low_num = base::NetToHost64(counter_.components64[1]);
+  uint64_t new_low_num = low_num + 1;
   counter_.components64[1] = base::HostToNet64(new_low_num);
 
   // If overflow occured then increment the most significant component.
@@ -36,8 +72,8 @@
 }
 
 void Encryptor::Counter::Write(void* buf) {
-  uint8* buf_ptr = reinterpret_cast<uint8*>(buf);
-  memcpy(buf_ptr, &counter_, sizeof(counter_));
+  uint8_t* buf_ptr = reinterpret_cast<uint8_t*>(buf);
+  SbMemoryCopy(buf_ptr, &counter_, sizeof(counter_));
 }
 
 size_t Encryptor::Counter::GetLengthInBytes() const {
@@ -45,9 +81,44 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-// Partial Encryptor Implementation.
+// Encryptor Implementation.
 
-bool Encryptor::SetCounter(const base::StringPiece& counter) {
+Encryptor::Encryptor() : key_(nullptr), mode_(CBC) {}
+
+Encryptor::~Encryptor() = default;
+
+bool Encryptor::Init(const SymmetricKey* key, Mode mode, base::StringPiece iv) {
+  DCHECK(key);
+  DCHECK(mode == CBC || mode == CTR);
+
+  EnsureOpenSSLInit();
+  if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
+    return false;
+
+  if (GetCipherForKey(key) == nullptr)
+    return false;
+
+  key_ = key;
+  mode_ = mode;
+  iv.CopyToString(&iv_);
+  return true;
+}
+
+bool Encryptor::Encrypt(base::StringPiece plaintext, std::string* ciphertext) {
+  CHECK(!plaintext.empty() || (mode_ == CBC));
+  return (mode_ == CTR) ?
+      CryptCTR(true, plaintext, ciphertext) :
+      Crypt(true, plaintext, ciphertext);
+}
+
+bool Encryptor::Decrypt(base::StringPiece ciphertext, std::string* plaintext) {
+  CHECK(!ciphertext.empty());
+  return (mode_ == CTR) ?
+      CryptCTR(false, ciphertext, plaintext) :
+      Crypt(false, ciphertext, plaintext);
+}
+
+bool Encryptor::SetCounter(base::StringPiece counter) {
   if (mode_ != CTR)
     return false;
   if (counter.length() != 16u)
@@ -57,41 +128,92 @@
   return true;
 }
 
-bool Encryptor::GenerateCounterMask(size_t plaintext_len,
-                                    uint8* mask,
-                                    size_t* mask_len) {
-  DCHECK_EQ(CTR, mode_);
-  CHECK(mask);
-  CHECK(mask_len);
+bool Encryptor::Crypt(bool do_encrypt,
+                      base::StringPiece input,
+                      std::string* output) {
+  DCHECK(key_);  // Must call Init() before En/De-crypt.
+  // Work on the result in a local variable, and then only transfer it to
+  // |output| on success to ensure no partial data is returned.
+  std::string result;
+  output->clear();
 
-  const size_t kBlockLength = counter_->GetLengthInBytes();
-  size_t blocks = (plaintext_len + kBlockLength - 1) / kBlockLength;
-  CHECK(blocks);
+  const EVP_CIPHER* cipher = GetCipherForKey(key_);
+  DCHECK(cipher);  // Already handled in Init();
 
-  *mask_len = blocks * kBlockLength;
+  const std::string& key = key_->key();
+  DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length());
+  DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length());
 
-  for (size_t i = 0; i < blocks; ++i) {
-    counter_->Write(mask);
-    mask += kBlockLength;
+  ScopedCipherCTX ctx;
+  if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr,
+                         reinterpret_cast<const uint8_t*>(key.data()),
+                         reinterpret_cast<const uint8_t*>(iv_.data()),
+                         do_encrypt))
+    return false;
 
-    bool ret = counter_->Increment();
-    if (!ret)
-      return false;
-  }
+  // When encrypting, add another block size of space to allow for any padding.
+  const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0);
+  CHECK_GT(output_size, 0u);
+  CHECK_GT(output_size + 1, input.size());
+  uint8_t* out_ptr =
+      reinterpret_cast<uint8_t*>(base::WriteInto(&result, output_size + 1));
+  int out_len;
+  if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len,
+                        reinterpret_cast<const uint8_t*>(input.data()),
+                        input.length()))
+    return false;
+
+  // Write out the final block plus padding (if any) to the end of the data
+  // just written.
+  int tail_len;
+  if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len))
+    return false;
+
+  out_len += tail_len;
+  DCHECK_LE(out_len, static_cast<int>(output_size));
+  result.resize(out_len);
+
+  output->swap(result);
   return true;
 }
 
-void Encryptor::MaskMessage(const void* plaintext,
-                            size_t plaintext_len,
-                            const void* mask,
-                            void* ciphertext) const {
-  DCHECK_EQ(CTR, mode_);
-  const uint8* plaintext_ptr = reinterpret_cast<const uint8*>(plaintext);
-  const uint8* mask_ptr = reinterpret_cast<const uint8*>(mask);
-  uint8* ciphertext_ptr = reinterpret_cast<uint8*>(ciphertext);
+bool Encryptor::CryptCTR(bool do_encrypt,
+                         base::StringPiece input,
+                         std::string* output) {
+  if (!counter_.get()) {
+    LOG(ERROR) << "Counter value not set in CTR mode.";
+    return false;
+  }
 
-  for (size_t i = 0; i < plaintext_len; ++i)
-    ciphertext_ptr[i] = plaintext_ptr[i] ^ mask_ptr[i];
+  AES_KEY aes_key;
+  if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key_->key().data()),
+                          key_->key().size() * 8, &aes_key) != 0) {
+    return false;
+  }
+
+  const size_t out_size = input.size();
+  CHECK_GT(out_size, 0u);
+  CHECK_GT(out_size + 1, input.size());
+
+  std::string result;
+  uint8_t* out_ptr =
+      reinterpret_cast<uint8_t*>(base::WriteInto(&result, out_size + 1));
+
+  uint8_t ivec[AES_BLOCK_SIZE] = { 0 };
+  uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 };
+  unsigned int block_offset = 0;
+
+  counter_->Write(ivec);
+
+  AES_ctr128_encrypt(reinterpret_cast<const uint8_t*>(input.data()), out_ptr,
+                     input.size(), &aes_key, ivec, ecount_buf, &block_offset);
+
+  // AES_ctr128_encrypt() updates |ivec|. Update the |counter_| here.
+  SetCounter(base::StringPiece(reinterpret_cast<const char*>(ivec),
+                               AES_BLOCK_SIZE));
+
+  output->swap(result);
+  return true;
 }
 
 }  // namespace crypto
diff --git a/src/crypto/encryptor.h b/src/crypto/encryptor.h
index 798a26f..7034eda 100644
--- a/src/crypto/encryptor.h
+++ b/src/crypto/encryptor.h
@@ -5,17 +5,13 @@
 #ifndef CRYPTO_ENCRYPTOR_H_
 #define CRYPTO_ENCRYPTOR_H_
 
+#include <memory>
 #include <string>
 
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
-
-#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-#include "crypto/scoped_nss_types.h"
-#endif
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -32,7 +28,7 @@
   // Only 128-bits counter is supported in this class.
   class CRYPTO_EXPORT Counter {
    public:
-    explicit Counter(const base::StringPiece& counter);
+    explicit Counter(base::StringPiece counter);
     ~Counter();
 
     // Increment the counter value.
@@ -47,24 +43,24 @@
 
    private:
     union {
-      uint32 components32[4];
-      uint64 components64[2];
+      uint32_t components32[4];
+      uint64_t components64[2];
     } counter_;
   };
 
   Encryptor();
-  virtual ~Encryptor();
+  ~Encryptor();
 
   // Initializes the encryptor using |key| and |iv|. Returns false if either the
   // key or the initialization vector cannot be used.
   //
   // If |mode| is CBC, |iv| must not be empty; if it is CTR, then |iv| must be
   // empty.
-  bool Init(SymmetricKey* key, Mode mode, const base::StringPiece& iv);
+  bool Init(const SymmetricKey* key, Mode mode, base::StringPiece iv);
 
   // Encrypts |plaintext| into |ciphertext|.  |plaintext| may only be empty if
   // the mode is CBC.
-  bool Encrypt(const base::StringPiece& plaintext, std::string* ciphertext);
+  bool Encrypt(base::StringPiece plaintext, std::string* ciphertext);
 
   // Decrypts |ciphertext| into |plaintext|.  |ciphertext| must not be empty.
   //
@@ -75,58 +71,26 @@
   // must either authenticate the ciphertext before decrypting it, or take
   // care to not report decryption failure. Otherwise it could inadvertently
   // be used as a padding oracle to attack the cryptosystem.
-  bool Decrypt(const base::StringPiece& ciphertext, std::string* plaintext);
+  bool Decrypt(base::StringPiece ciphertext, std::string* plaintext);
 
   // Sets the counter value when in CTR mode. Currently only 128-bits
   // counter value is supported.
   //
   // Returns true only if update was successful.
-  bool SetCounter(const base::StringPiece& counter);
+  bool SetCounter(base::StringPiece counter);
 
   // TODO(albertb): Support streaming encryption.
 
  private:
-  // Generates a mask using |counter_| to be used for encryption in CTR mode.
-  // Resulting mask will be written to |mask| with |mask_len| bytes.
-  //
-  // Make sure there's enough space in mask when calling this method.
-  // Reserve at least |plaintext_len| + 16 bytes for |mask|.
-  //
-  // The generated mask will always have at least |plaintext_len| bytes and
-  // will be a multiple of the counter length.
-  //
-  // This method is used only in CTR mode.
-  //
-  // Returns false if this call failed.
-  bool GenerateCounterMask(size_t plaintext_len,
-                           uint8* mask,
-                           size_t* mask_len);
-
-  // Mask the |plaintext| message using |mask|. The output will be written to
-  // |ciphertext|. |ciphertext| must have at least |plaintext_len| bytes.
-  void MaskMessage(const void* plaintext,
-                   size_t plaintext_len,
-                   const void* mask,
-                   void* ciphertext) const;
-
-  SymmetricKey* key_;
+  const SymmetricKey* key_;
   Mode mode_;
-  scoped_ptr<Counter> counter_;
+  std::unique_ptr<Counter> counter_;
 
-#if defined(USE_OPENSSL)
-  bool Crypt(bool encrypt,  // Pass true to encrypt, false to decrypt.
-             const base::StringPiece& input,
+  bool Crypt(bool do_encrypt,  // Pass true to encrypt, false to decrypt.
+             base::StringPiece input,
              std::string* output);
+  bool CryptCTR(bool do_encrypt, base::StringPiece input, std::string* output);
   std::string iv_;
-#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-  bool Crypt(PK11Context* context,
-             const base::StringPiece& input,
-             std::string* output);
-  bool CryptCTR(PK11Context* context,
-                const base::StringPiece& input,
-                std::string* output);
-  ScopedSECItem param_;
-#endif
 };
 
 }  // namespace crypto
diff --git a/src/crypto/encryptor_openssl.cc b/src/crypto/encryptor_openssl.cc
deleted file mode 100644
index cb26e22..0000000
--- a/src/crypto/encryptor_openssl.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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 "crypto/encryptor.h"
-
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "crypto/openssl_util.h"
-#include "crypto/symmetric_key.h"
-
-namespace crypto {
-
-namespace {
-
-const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) {
-  switch (key->key().length()) {
-    case 16: return EVP_aes_128_cbc();
-    case 24: return EVP_aes_192_cbc();
-    case 32: return EVP_aes_256_cbc();
-    default: return NULL;
-  }
-}
-
-// On destruction this class will cleanup the ctx, and also clear the OpenSSL
-// ERR stack as a convenience.
-class ScopedCipherCTX {
- public:
-  explicit ScopedCipherCTX() {
-    EVP_CIPHER_CTX_init(&ctx_);
-  }
-  ~ScopedCipherCTX() {
-    EVP_CIPHER_CTX_cleanup(&ctx_);
-    ClearOpenSSLERRStack(FROM_HERE);
-  }
-  EVP_CIPHER_CTX* get() { return &ctx_; }
-
- private:
-  EVP_CIPHER_CTX ctx_;
-};
-
-}  // namespace
-
-Encryptor::Encryptor()
-    : key_(NULL),
-      mode_(CBC) {
-}
-
-Encryptor::~Encryptor() {
-}
-
-bool Encryptor::Init(SymmetricKey* key,
-                     Mode mode,
-                     const base::StringPiece& iv) {
-  DCHECK(key);
-  DCHECK_EQ(CBC, mode);
-
-  EnsureOpenSSLInit();
-  if (iv.size() != AES_BLOCK_SIZE)
-    return false;
-
-  if (GetCipherForKey(key) == NULL)
-    return false;
-
-  key_ = key;
-  mode_ = mode;
-  iv.CopyToString(&iv_);
-  return true;
-}
-
-bool Encryptor::Encrypt(const base::StringPiece& plaintext,
-                        std::string* ciphertext) {
-  CHECK(!plaintext.empty() || (mode_ == CBC));
-  return Crypt(true, plaintext, ciphertext);
-}
-
-bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
-                        std::string* plaintext) {
-  CHECK(!ciphertext.empty());
-  return Crypt(false, ciphertext, plaintext);
-}
-
-bool Encryptor::Crypt(bool do_encrypt,
-                      const base::StringPiece& input,
-                      std::string* output) {
-  DCHECK(key_);  // Must call Init() before En/De-crypt.
-  // Work on the result in a local variable, and then only transfer it to
-  // |output| on success to ensure no partial data is returned.
-  std::string result;
-  output->clear();
-
-  const EVP_CIPHER* cipher = GetCipherForKey(key_);
-  DCHECK(cipher);  // Already handled in Init();
-
-  const std::string& key = key_->key();
-  DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast<int>(iv_.length()));
-  DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast<int>(key.length()));
-
-  ScopedCipherCTX ctx;
-  if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL,
-                         reinterpret_cast<const uint8*>(key.data()),
-                         reinterpret_cast<const uint8*>(iv_.data()),
-                         do_encrypt))
-    return false;
-
-  // When encrypting, add another block size of space to allow for any padding.
-  const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0);
-  CHECK_GT(output_size, 0u);
-  CHECK_GT(output_size + 1, input.size());
-  uint8* out_ptr = reinterpret_cast<uint8*>(WriteInto(&result,
-                                                      output_size + 1));
-  int out_len;
-  if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len,
-                        reinterpret_cast<const uint8*>(input.data()),
-                        input.length()))
-    return false;
-
-  // Write out the final block plus padding (if any) to the end of the data
-  // just written.
-  int tail_len;
-  if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len))
-    return false;
-
-  out_len += tail_len;
-  DCHECK_LE(out_len, static_cast<int>(output_size));
-  result.resize(out_len);
-
-  output->swap(result);
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/encryptor_unittest.cc b/src/crypto/encryptor_unittest.cc
index b0ec4bc..f62947f 100644
--- a/src/crypto/encryptor_unittest.cc
+++ b/src/crypto/encryptor_unittest.cc
@@ -4,18 +4,21 @@
 
 #include "crypto/encryptor.h"
 
+#include <memory>
 #include <string>
 
-#include "base/memory/scoped_ptr.h"
-#include "base/string_number_conversions.h"
+#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
 #include "crypto/symmetric_key.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(EncryptorTest, EncryptDecrypt) {
-  scoped_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256));
-  EXPECT_TRUE(NULL != key.get());
+  EXPECT_TRUE(key.get());
 
   crypto::Encryptor encryptor;
   // The IV must be exactly as long as the cipher block size.
@@ -29,37 +32,37 @@
 
   EXPECT_LT(0U, ciphertext.size());
 
-  std::string decypted;
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
+  std::string decrypted;
+  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted));
 
-  EXPECT_EQ(plaintext, decypted);
+  EXPECT_EQ(plaintext, decrypted);
 }
 
 TEST(EncryptorTest, DecryptWrongKey) {
-  scoped_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256));
-  EXPECT_TRUE(NULL != key.get());
+  EXPECT_TRUE(key.get());
 
   // A wrong key that can be detected by implementations that validate every
   // byte in the padding.
-  scoped_ptr<crypto::SymmetricKey> wrong_key(
-        crypto::SymmetricKey::DeriveKeyFromPassword(
-            crypto::SymmetricKey::AES, "wrongword", "sweetest", 1000, 256));
-  EXPECT_TRUE(NULL != wrong_key.get());
+  std::unique_ptr<crypto::SymmetricKey> wrong_key(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, "wrongword", "sweetest", 1000, 256));
+  EXPECT_TRUE(wrong_key.get());
 
   // A wrong key that can't be detected by any implementation.  The password
   // "wrongword;" would also work.
-  scoped_ptr<crypto::SymmetricKey> wrong_key2(
-        crypto::SymmetricKey::DeriveKeyFromPassword(
-            crypto::SymmetricKey::AES, "wrongword+", "sweetest", 1000, 256));
-  EXPECT_TRUE(NULL != wrong_key2.get());
+  std::unique_ptr<crypto::SymmetricKey> wrong_key2(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, "wrongword+", "sweetest", 1000, 256));
+  EXPECT_TRUE(wrong_key2.get());
 
   // A wrong key that can be detected by all implementations.
-  scoped_ptr<crypto::SymmetricKey> wrong_key3(
-        crypto::SymmetricKey::DeriveKeyFromPassword(
-            crypto::SymmetricKey::AES, "wrongwordx", "sweetest", 1000, 256));
-  EXPECT_TRUE(NULL != wrong_key3.get());
+  std::unique_ptr<crypto::SymmetricKey> wrong_key3(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, "wrongwordx", "sweetest", 1000, 256));
+  EXPECT_TRUE(wrong_key3.get());
 
   crypto::Encryptor encryptor;
   // The IV must be exactly as long as the cipher block size.
@@ -84,7 +87,7 @@
               static_cast<unsigned char>(ciphertext[i]));
   }
 
-  std::string decypted;
+  std::string decrypted;
 
   // This wrong key causes the last padding byte to be 5, which is a valid
   // padding length, and the second to last padding byte to be 137, which is
@@ -92,35 +95,197 @@
   // determine the padding length without checking every padding byte,
   // Encryptor::Decrypt() will still return true.  This is the case for NSS
   // (crbug.com/124434).
-#if !defined(USE_NSS) && !defined(OS_WIN) && !defined(OS_MACOSX)
   crypto::Encryptor decryptor;
   EXPECT_TRUE(decryptor.Init(wrong_key.get(), crypto::Encryptor::CBC, iv));
-  EXPECT_FALSE(decryptor.Decrypt(ciphertext, &decypted));
-#endif
+  EXPECT_FALSE(decryptor.Decrypt(ciphertext, &decrypted));
 
   // This demonstrates that not all wrong keys can be detected by padding
   // error. This wrong key causes the last padding byte to be 1, which is
   // a valid padding block of length 1.
   crypto::Encryptor decryptor2;
   EXPECT_TRUE(decryptor2.Init(wrong_key2.get(), crypto::Encryptor::CBC, iv));
-  EXPECT_TRUE(decryptor2.Decrypt(ciphertext, &decypted));
+  EXPECT_TRUE(decryptor2.Decrypt(ciphertext, &decrypted));
 
   // This wrong key causes the last padding byte to be 253, which should be
   // rejected by all implementations.
   crypto::Encryptor decryptor3;
   EXPECT_TRUE(decryptor3.Init(wrong_key3.get(), crypto::Encryptor::CBC, iv));
-  EXPECT_FALSE(decryptor3.Decrypt(ciphertext, &decypted));
+  EXPECT_FALSE(decryptor3.Decrypt(ciphertext, &decrypted));
 }
 
-// CTR mode encryption is only implemented using NSS.
-#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+namespace {
+
+// From NIST SP 800-38a test cast:
+// - F.5.1 CTR-AES128.Encrypt
+// - F.5.6 CTR-AES256.Encrypt
+// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+const unsigned char kAES128CTRKey[] = {
+  0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+
+const unsigned char kAES256CTRKey[] = {
+  0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+  0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+  0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+  0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+
+const unsigned char kAESCTRInitCounter[] = {
+  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+const unsigned char kAESCTRPlaintext[] = {
+  // Block #1
+  0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+  // Block #2
+  0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+  0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+  // Block #3
+  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+  0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+  // Block #4
+  0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+  0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+const unsigned char kAES128CTRCiphertext[] = {
+  // Block #1
+  0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
+  0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
+  // Block #2
+  0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff,
+  0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
+  // Block #3
+  0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e,
+  0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
+  // Block #4
+  0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1,
+  0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
+};
+
+const unsigned char kAES256CTRCiphertext[] = {
+  // Block #1
+  0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5,
+  0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28,
+  // Block #2
+  0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a,
+  0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5,
+  // Block #3
+  0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c,
+  0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d,
+  // Block #4
+  0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6,
+  0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6
+};
+
+void TestAESCTREncrypt(
+    const unsigned char* key, size_t key_size,
+    const unsigned char* init_counter, size_t init_counter_size,
+    const unsigned char* plaintext, size_t plaintext_size,
+    const unsigned char* ciphertext, size_t ciphertext_size) {
+  std::string key_str(reinterpret_cast<const char*>(key), key_size);
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key_str));
+  ASSERT_TRUE(sym_key.get());
+
+  crypto::Encryptor encryptor;
+  EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, ""));
+
+  base::StringPiece init_counter_str(
+      reinterpret_cast<const char*>(init_counter), init_counter_size);
+  base::StringPiece plaintext_str(
+      reinterpret_cast<const char*>(plaintext), plaintext_size);
+
+  EXPECT_TRUE(encryptor.SetCounter(init_counter_str));
+  std::string encrypted;
+  EXPECT_TRUE(encryptor.Encrypt(plaintext_str, &encrypted));
+
+  EXPECT_EQ(ciphertext_size, encrypted.size());
+  EXPECT_EQ(0, SbMemoryCompare(encrypted.data(), ciphertext, encrypted.size()));
+
+  std::string decrypted;
+  EXPECT_TRUE(encryptor.SetCounter(init_counter_str));
+  EXPECT_TRUE(encryptor.Decrypt(encrypted, &decrypted));
+
+  EXPECT_EQ(plaintext_str, decrypted);
+}
+
+void TestAESCTRMultipleDecrypt(
+    const unsigned char* key, size_t key_size,
+    const unsigned char* init_counter, size_t init_counter_size,
+    const unsigned char* plaintext, size_t plaintext_size,
+    const unsigned char* ciphertext, size_t ciphertext_size) {
+  std::string key_str(reinterpret_cast<const char*>(key), key_size);
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key_str));
+  ASSERT_TRUE(sym_key.get());
+
+  crypto::Encryptor encryptor;
+  EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, ""));
+
+  // Counter is set only once.
+  EXPECT_TRUE(encryptor.SetCounter(base::StringPiece(
+      reinterpret_cast<const char*>(init_counter), init_counter_size)));
+
+  std::string ciphertext_str(reinterpret_cast<const char*>(ciphertext),
+                             ciphertext_size);
+
+  int kTestDecryptSizes[] = { 32, 16, 8 };
+
+  int offset = 0;
+  for (size_t i = 0; i < arraysize(kTestDecryptSizes); ++i) {
+    std::string decrypted;
+    size_t len = kTestDecryptSizes[i];
+    EXPECT_TRUE(
+        encryptor.Decrypt(ciphertext_str.substr(offset, len), &decrypted));
+    EXPECT_EQ(len, decrypted.size());
+    EXPECT_EQ(0, SbMemoryCompare(decrypted.data(), plaintext + offset, len));
+    offset += len;
+  }
+}
+
+}  // namespace
+
+TEST(EncryptorTest, EncryptAES128CTR) {
+  TestAESCTREncrypt(
+      kAES128CTRKey, arraysize(kAES128CTRKey),
+      kAESCTRInitCounter, arraysize(kAESCTRInitCounter),
+      kAESCTRPlaintext, arraysize(kAESCTRPlaintext),
+      kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext));
+}
+
+TEST(EncryptorTest, EncryptAES256CTR) {
+  TestAESCTREncrypt(
+      kAES256CTRKey, arraysize(kAES256CTRKey),
+      kAESCTRInitCounter, arraysize(kAESCTRInitCounter),
+      kAESCTRPlaintext, arraysize(kAESCTRPlaintext),
+      kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext));
+}
+
+TEST(EncryptorTest, EncryptAES128CTR_MultipleDecrypt) {
+  TestAESCTRMultipleDecrypt(
+      kAES128CTRKey, arraysize(kAES128CTRKey),
+      kAESCTRInitCounter, arraysize(kAESCTRInitCounter),
+      kAESCTRPlaintext, arraysize(kAESCTRPlaintext),
+      kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext));
+}
+
+TEST(EncryptorTest, EncryptAES256CTR_MultipleDecrypt) {
+  TestAESCTRMultipleDecrypt(
+      kAES256CTRKey, arraysize(kAES256CTRKey),
+      kAESCTRInitCounter, arraysize(kAESCTRInitCounter),
+      kAESCTRPlaintext, arraysize(kAESCTRPlaintext),
+      kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext));
+}
 
 TEST(EncryptorTest, EncryptDecryptCTR) {
-  scoped_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::GenerateRandomKey(
-          crypto::SymmetricKey::AES, 128));
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 128));
 
-  EXPECT_TRUE(NULL != key.get());
+  EXPECT_TRUE(key.get());
   const std::string kInitialCounter = "0000000000000000";
 
   crypto::Encryptor encryptor;
@@ -132,10 +297,10 @@
   EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext));
   EXPECT_LT(0U, ciphertext.size());
 
-  std::string decypted;
+  std::string decrypted;
   EXPECT_TRUE(encryptor.SetCounter(kInitialCounter));
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
-  EXPECT_EQ(plaintext, decypted);
+  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted));
+  EXPECT_EQ(plaintext, decrypted);
 
   plaintext = "0123456789012345";
   EXPECT_TRUE(encryptor.SetCounter(kInitialCounter));
@@ -143,8 +308,8 @@
   EXPECT_LT(0U, ciphertext.size());
 
   EXPECT_TRUE(encryptor.SetCounter(kInitialCounter));
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
-  EXPECT_EQ(plaintext, decypted);
+  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted));
+  EXPECT_EQ(plaintext, decrypted);
 }
 
 TEST(EncryptorTest, CTRCounter) {
@@ -159,8 +324,8 @@
   for (int i = 0; i < 10; ++i)
     counter1.Increment();
   counter1.Write(buf);
-  EXPECT_EQ(0, memcmp(buf, kTest1, 15));
-  EXPECT_TRUE(buf[15] == 10);
+  EXPECT_EQ(0, SbMemoryCompare(buf, kTest1, 15));
+  EXPECT_EQ(10, buf[15]);
 
   // Check corner cases.
   const unsigned char kTest2[] = {
@@ -173,7 +338,7 @@
       std::string(reinterpret_cast<const char*>(kTest2), kCounterSize));
   counter2.Increment();
   counter2.Write(buf);
-  EXPECT_EQ(0, memcmp(buf, kExpect2, kCounterSize));
+  EXPECT_EQ(0, SbMemoryCompare(buf, kExpect2, kCounterSize));
 
   const unsigned char kTest3[] = {
       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -185,11 +350,9 @@
       std::string(reinterpret_cast<const char*>(kTest3), kCounterSize));
   counter3.Increment();
   counter3.Write(buf);
-  EXPECT_EQ(0, memcmp(buf, kExpect3, kCounterSize));
+  EXPECT_EQ(0, SbMemoryCompare(buf, kExpect3, kCounterSize));
 }
 
-#endif
-
 // TODO(wtc): add more known-answer tests.  Test vectors are available from
 // http://www.ietf.org/rfc/rfc3602
 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
@@ -199,17 +362,17 @@
 // NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt.
 TEST(EncryptorTest, EncryptAES256CBC) {
   // From NIST SP 800-38a test cast F.2.5 CBC-AES256.Encrypt.
-  static const unsigned char raw_key[] = {
+  static const unsigned char kRawKey[] = {
     0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
     0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
     0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
     0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
   };
-  static const unsigned char raw_iv[] = {
+  static const unsigned char kRawIv[] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   };
-  static const unsigned char raw_plaintext[] = {
+  static const unsigned char kRawPlaintext[] = {
     // Block #1
     0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
     0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
@@ -223,7 +386,7 @@
     0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
     0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
   };
-  static const unsigned char raw_ciphertext[] = {
+  static const unsigned char kRawCiphertext[] = {
     // Block #1
     0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
     0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
@@ -241,29 +404,30 @@
     0xe0, 0xc2, 0xa7, 0x2b, 0x4d, 0x80, 0xe6, 0x44
   };
 
-  std::string key(reinterpret_cast<const char*>(raw_key), sizeof(raw_key));
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
+  std::string key(reinterpret_cast<const char*>(kRawKey), sizeof(kRawKey));
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  ASSERT_TRUE(sym_key.get());
 
   crypto::Encryptor encryptor;
   // The IV must be exactly as long a the cipher block size.
-  std::string iv(reinterpret_cast<const char*>(raw_iv), sizeof(raw_iv));
+  std::string iv(reinterpret_cast<const char*>(kRawIv), sizeof(kRawIv));
   EXPECT_EQ(16U, iv.size());
   EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
 
-  std::string plaintext(reinterpret_cast<const char*>(raw_plaintext),
-                        sizeof(raw_plaintext));
+  std::string plaintext(reinterpret_cast<const char*>(kRawPlaintext),
+                        sizeof(kRawPlaintext));
   std::string ciphertext;
   EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext));
 
-  EXPECT_EQ(sizeof(raw_ciphertext), ciphertext.size());
-  EXPECT_EQ(0, memcmp(ciphertext.data(), raw_ciphertext, ciphertext.size()));
+  EXPECT_EQ(sizeof(kRawCiphertext), ciphertext.size());
+  EXPECT_EQ(
+      0, SbMemoryCompare(ciphertext.data(), kRawCiphertext, ciphertext.size()));
 
-  std::string decypted;
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
+  std::string decrypted;
+  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted));
 
-  EXPECT_EQ(plaintext, decypted);
+  EXPECT_EQ(plaintext, decrypted);
 }
 
 // Expected output derived from the NSS implementation.
@@ -275,9 +439,9 @@
       "D4A67A0BA33C30F207344D81D1E944BBE65587C3D7D9939A"
       "C070C62B9C15A3EA312EA4AD1BC7929F4D3C16B03AD5ADA8";
 
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  ASSERT_TRUE(sym_key.get());
 
   crypto::Encryptor encryptor;
   // The IV must be exactly as long a the cipher block size.
@@ -289,60 +453,33 @@
   EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(),
                                                      ciphertext.size()));
 
-  std::string decypted;
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
-  EXPECT_EQ(plaintext, decypted);
+  std::string decrypted;
+  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted));
+  EXPECT_EQ(plaintext, decrypted);
 }
 
-// Expected output derived from the NSS implementation.
-TEST(EncryptorTest, EncryptAES192CBCRegression) {
-  std::string key = "192bitsIsTwentyFourByte!";
-  std::string iv = "Sweet Sixteen IV";
-  std::string plaintext = "Small text";
-  std::string expected_ciphertext_hex = "78DE5D7C2714FC5C61346C5416F6C89A";
-
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
-
-  crypto::Encryptor encryptor;
-  // The IV must be exactly as long a the cipher block size.
-  EXPECT_EQ(16U, iv.size());
-  EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
-
-  std::string ciphertext;
-  EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext));
-  EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(),
-                                                     ciphertext.size()));
-
-  std::string decypted;
-  EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted));
-  EXPECT_EQ(plaintext, decypted);
-}
-
-// Not all platforms allow import/generation of symmetric keys with an
-// unsupported size.
-#if !defined(USE_NSS) && !defined(OS_WIN) && !defined(OS_MACOSX)
+// Symmetric keys with an unsupported size should be rejected. Whether they are
+// rejected by SymmetricKey::Import or Encryptor::Init depends on the platform.
 TEST(EncryptorTest, UnsupportedKeySize) {
   std::string key = "7 = bad";
   std::string iv = "Sweet Sixteen IV";
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  if (!sym_key.get())
+    return;
 
   crypto::Encryptor encryptor;
-  // The IV must be exactly as long a the cipher block size.
+  // The IV must be exactly as long as the cipher block size.
   EXPECT_EQ(16U, iv.size());
   EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
 }
-#endif  // unsupported platforms.
 
 TEST(EncryptorTest, UnsupportedIV) {
   std::string key = "128=SixteenBytes";
   std::string iv = "OnlyForteen :(";
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  ASSERT_TRUE(sym_key.get());
 
   crypto::Encryptor encryptor;
   EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
@@ -354,9 +491,9 @@
   std::string plaintext;
   std::string expected_ciphertext_hex = "8518B8878D34E7185E300D0FCC426396";
 
-  scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import(
-      crypto::SymmetricKey::AES, key));
-  ASSERT_TRUE(NULL != sym_key.get());
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  ASSERT_TRUE(sym_key.get());
 
   crypto::Encryptor encryptor;
   // The IV must be exactly as long a the cipher block size.
@@ -368,3 +505,29 @@
   EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(),
                                                      ciphertext.size()));
 }
+
+TEST(EncryptorTest, CipherTextNotMultipleOfBlockSize) {
+  std::string key = "128=SixteenBytes";
+  std::string iv = "Sweet Sixteen IV";
+
+  std::unique_ptr<crypto::SymmetricKey> sym_key(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key));
+  ASSERT_TRUE(sym_key.get());
+
+  crypto::Encryptor encryptor;
+  // The IV must be exactly as long a the cipher block size.
+  EXPECT_EQ(16U, iv.size());
+  EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv));
+
+  // Use a separately allocated array to improve the odds of the memory tools
+  // catching invalid accesses.
+  //
+  // Otherwise when using std::string as the other tests do, accesses several
+  // bytes off the end of the buffer may fall inside the reservation of
+  // the string and not be detected.
+  std::unique_ptr<char[]> ciphertext(new char[1]);
+
+  std::string plaintext;
+  EXPECT_FALSE(
+      encryptor.Decrypt(base::StringPiece(ciphertext.get(), 1), &plaintext));
+}
diff --git a/src/crypto/ghash.cc b/src/crypto/ghash.cc
deleted file mode 100644
index 99eae03..0000000
--- a/src/crypto/ghash.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (c) 2012 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/ghash.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/sys_byteorder.h"
-
-namespace crypto {
-
-// GaloisHash is a polynomial authenticator that works in GF(2^128).
-//
-// Elements of the field are represented in `little-endian' order (which
-// matches the description in the paper[1]), thus the most significant bit is
-// the right-most bit. (This is backwards from the way that everybody else does
-// it.)
-//
-// We store field elements in a pair of such `little-endian' uint64s. So the
-// value one is represented by {low = 2**63, high = 0} and doubling a value
-// involves a *right* shift.
-//
-// [1] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-
-namespace {
-
-// Get64 reads a 64-bit, big-endian number from |bytes|.
-uint64 Get64(const uint8 bytes[8]) {
-  uint64 t;
-  memcpy(&t, bytes, sizeof(t));
-  return base::NetToHost64(t);
-}
-
-// Put64 writes |x| to |bytes| as a 64-bit, big-endian number.
-void Put64(uint8 bytes[8], uint64 x) {
-  x = base::HostToNet64(x);
-  memcpy(bytes, &x, sizeof(x));
-}
-
-// Reverse reverses the order of the bits of 4-bit number in |i|.
-int Reverse(int i) {
-  i = ((i << 2) & 0xc) | ((i >> 2) & 0x3);
-  i = ((i << 1) & 0xa) | ((i >> 1) & 0x5);
-  return i;
-}
-
-}  // namespace
-
-GaloisHash::GaloisHash(const uint8 key[16]) {
-  Reset();
-
-  // We precompute 16 multiples of |key|. However, when we do lookups into this
-  // table we'll be using bits from a field element and therefore the bits will
-  // be in the reverse order. So normally one would expect, say, 4*key to be in
-  // index 4 of the table but due to this bit ordering it will actually be in
-  // index 0010 (base 2) = 2.
-  FieldElement x = {Get64(key), Get64(key+8)};
-  product_table_[0].low = 0;
-  product_table_[0].hi = 0;
-  product_table_[Reverse(1)] = x;
-
-  for (int i = 0; i < 16; i += 2) {
-    product_table_[Reverse(i)] = Double(product_table_[Reverse(i/2)]);
-    product_table_[Reverse(i+1)] = Add(product_table_[Reverse(i)], x);
-  }
-}
-
-void GaloisHash::Reset() {
-  state_ = kHashingAdditionalData;
-  additional_bytes_ = 0;
-  ciphertext_bytes_ = 0;
-  buf_used_ = 0;
-  y_.low = 0;
-  y_.hi = 0;
-}
-
-void GaloisHash::UpdateAdditional(const uint8* data, size_t length) {
-  DCHECK_EQ(state_, kHashingAdditionalData);
-  additional_bytes_ += length;
-  Update(data, length);
-}
-
-void GaloisHash::UpdateCiphertext(const uint8* data, size_t length) {
-  if (state_ == kHashingAdditionalData) {
-    // If there's any remaining additional data it's zero padded to the next
-    // full block.
-    if (buf_used_ > 0) {
-      memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_);
-      UpdateBlocks(buf_, 1);
-      buf_used_ = 0;
-    }
-    state_ = kHashingCiphertext;
-  }
-
-  DCHECK_EQ(state_, kHashingCiphertext);
-  ciphertext_bytes_ += length;
-  Update(data, length);
-}
-
-void GaloisHash::Finish(void* output, size_t len) {
-  DCHECK(state_ != kComplete);
-
-  if (buf_used_ > 0) {
-    // If there's any remaining data (additional data or ciphertext), it's zero
-    // padded to the next full block.
-    memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_);
-    UpdateBlocks(buf_, 1);
-    buf_used_ = 0;
-  }
-
-  state_ = kComplete;
-
-  // The lengths of the additional data and ciphertext are included as the last
-  // block. The lengths are the number of bits.
-  y_.low ^= additional_bytes_*8;
-  y_.hi ^= ciphertext_bytes_*8;
-  MulAfterPrecomputation(product_table_, &y_);
-
-  uint8 *result, result_tmp[16];
-  if (len >= 16) {
-    result = reinterpret_cast<uint8*>(output);
-  } else {
-    result = result_tmp;
-  }
-
-  Put64(result, y_.low);
-  Put64(result + 8, y_.hi);
-
-  if (len < 16)
-    memcpy(output, result_tmp, len);
-}
-
-// static
-GaloisHash::FieldElement GaloisHash::Add(
-    const FieldElement& x,
-    const FieldElement& y) {
-  // Addition in a characteristic 2 field is just XOR.
-  FieldElement z = {x.low^y.low, x.hi^y.hi};
-  return z;
-}
-
-// static
-GaloisHash::FieldElement GaloisHash::Double(const FieldElement& x) {
-  const bool msb_set = x.hi & 1;
-
-  FieldElement xx;
-  // Because of the bit-ordering, doubling is actually a right shift.
-  xx.hi = x.hi >> 1;
-  xx.hi |= x.low << 63;
-  xx.low = x.low >> 1;
-
-  // If the most-significant bit was set before shifting then it, conceptually,
-  // becomes a term of x^128. This is greater than the irreducible polynomial
-  // so the result has to be reduced. The irreducible polynomial is
-  // 1+x+x^2+x^7+x^128. We can subtract that to eliminate the term at x^128
-  // which also means subtracting the other four terms. In characteristic 2
-  // fields, subtraction == addition == XOR.
-  if (msb_set)
-    xx.low ^= 0xe100000000000000ULL;
-
-  return xx;
-}
-
-void GaloisHash::MulAfterPrecomputation(const FieldElement* table,
-                                        FieldElement* x) {
-  FieldElement z = {0, 0};
-
-  // In order to efficiently multiply, we use the precomputed table of i*key,
-  // for i in 0..15, to handle four bits at a time. We could obviously use
-  // larger tables for greater speedups but the next convenient table size is
-  // 4K, which is a little large.
-  //
-  // In other fields one would use bit positions spread out across the field in
-  // order to reduce the number of doublings required. However, in
-  // characteristic 2 fields, repeated doublings are exceptionally cheap and
-  // it's not worth spending more precomputation time to eliminate them.
-  for (unsigned i = 0; i < 2; i++) {
-    uint64 word;
-    if (i == 0) {
-      word = x->hi;
-    } else {
-      word = x->low;
-    }
-
-    for (unsigned j = 0; j < 64; j += 4) {
-      Mul16(&z);
-      // the values in |table| are ordered for little-endian bit positions. See
-      // the comment in the constructor.
-      const FieldElement& t = table[word & 0xf];
-      z.low ^= t.low;
-      z.hi ^= t.hi;
-      word >>= 4;
-    }
-  }
-
-  *x = z;
-}
-
-// kReductionTable allows for rapid multiplications by 16. A multiplication by
-// 16 is a right shift by four bits, which results in four bits at 2**128.
-// These terms have to be eliminated by dividing by the irreducible polynomial.
-// In GHASH, the polynomial is such that all the terms occur in the
-// least-significant 8 bits, save for the term at x^128. Therefore we can
-// precompute the value to be added to the field element for each of the 16 bit
-// patterns at 2**128 and the values fit within 12 bits.
-static const uint16 kReductionTable[16] = {
-  0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
-  0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
-};
-
-// static
-void GaloisHash::Mul16(FieldElement* x) {
-  const unsigned msw = x->hi & 0xf;
-  x->hi >>= 4;
-  x->hi |= x->low << 60;
-  x->low >>= 4;
-  x->low ^= static_cast<uint64>(kReductionTable[msw]) << 48;
-}
-
-void GaloisHash::UpdateBlocks(const uint8* bytes, size_t num_blocks) {
-  for (size_t i = 0; i < num_blocks; i++) {
-    y_.low ^= Get64(bytes);
-    bytes += 8;
-    y_.hi ^= Get64(bytes);
-    bytes += 8;
-    MulAfterPrecomputation(product_table_, &y_);
-  }
-}
-
-void GaloisHash::Update(const uint8* data, size_t length) {
-  if (buf_used_ > 0) {
-    const size_t n = std::min(length, buf_used_);
-    memcpy(&buf_[buf_used_], data, n);
-    buf_used_ += n;
-    length -= n;
-    data += n;
-
-    if (buf_used_ == sizeof(buf_)) {
-      UpdateBlocks(buf_, 1);
-      buf_used_ = 0;
-    }
-  }
-
-  if (length >= 16) {
-    const size_t n = length / 16;
-    UpdateBlocks(data, n);
-    length -= n*16;
-    data += n*16;
-  }
-
-  if (length > 0) {
-    memcpy(buf_, data, length);
-    buf_used_ = length;
-  }
-}
-
-}  // namespace crypto
diff --git a/src/crypto/ghash.h b/src/crypto/ghash.h
deleted file mode 100644
index 6dc247b..0000000
--- a/src/crypto/ghash.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2012 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 "base/basictypes.h"
-#include "crypto/crypto_export.h"
-
-namespace crypto {
-
-// GaloisHash implements the polynomial authenticator part of GCM as specified
-// in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-// Specifically it implements the GHASH function, defined in section 2.3 of
-// that document.
-//
-// In SP-800-38D, GHASH is defined differently and takes only a single data
-// argument. But it is always called with an argument of a certain form:
-//   GHASH_H (A || 0^v || C || 0^u || [len(A)]_64 || [len(C)]_64)
-// This mirrors how the gcm-revised-spec.pdf version of GHASH handles its two
-// data arguments. The two GHASH functions therefore differ only in whether the
-// data is formatted inside or outside of the function.
-//
-// WARNING: do not use this as a generic authenticator. Polynomial
-// authenticators must be used in the correct manner and any use outside of GCM
-// requires careful consideration.
-//
-// WARNING: this code is not constant time. However, in all likelihood, nor is
-// the implementation of AES that is used.
-class CRYPTO_EXPORT_PRIVATE GaloisHash {
- public:
-  explicit GaloisHash(const uint8 key[16]);
-
-  // Reset prepares to digest a fresh message with the same key. This is more
-  // efficient than creating a fresh object.
-  void Reset();
-
-  // UpdateAdditional hashes in `additional' data. This is data that is not
-  // encrypted, but is covered by the authenticator. All additional data must
-  // be written before any ciphertext is written.
-  void UpdateAdditional(const uint8* data, size_t length);
-
-  // UpdateCiphertext hashes in ciphertext to be authenticated.
-  void UpdateCiphertext(const uint8* data, size_t length);
-
-  // Finish completes the hash computation and writes at most |len| bytes of
-  // the result to |output|.
-  void Finish(void* output, size_t len);
-
- private:
-  enum State {
-    kHashingAdditionalData,
-    kHashingCiphertext,
-    kComplete,
-  };
-
-  struct FieldElement {
-    uint64 low, hi;
-  };
-
-  // Add returns |x|+|y|.
-  static FieldElement Add(const FieldElement& x, const FieldElement& y);
-  // Double returns 2*|x|.
-  static FieldElement Double(const FieldElement& x);
-  // MulAfterPrecomputation sets |x| = |x|*h where h is |table[1]| and
-  // table[i] = i*h for i=0..15.
-  static void MulAfterPrecomputation(const FieldElement* table,
-                                     FieldElement* x);
-  // Mul16 sets |x| = 16*|x|.
-  static void Mul16(FieldElement* x);
-
-  // UpdateBlocks processes |num_blocks| 16-bytes blocks from |bytes|.
-  void UpdateBlocks(const uint8* bytes, size_t num_blocks);
-  // Update processes |length| bytes from |bytes| and calls UpdateBlocks on as
-  // much data as possible. It uses |buf_| to buffer any remaining data and
-  // always consumes all of |bytes|.
-  void Update(const uint8* bytes, size_t length);
-
-  FieldElement y_;
-  State state_;
-  size_t additional_bytes_;
-  size_t ciphertext_bytes_;
-  uint8 buf_[16];
-  size_t buf_used_;
-  FieldElement product_table_[16];
-};
-
-}  // namespace crypto
diff --git a/src/crypto/ghash_unittest.cc b/src/crypto/ghash_unittest.cc
deleted file mode 100644
index c491f76..0000000
--- a/src/crypto/ghash_unittest.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2012 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/ghash.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace crypto {
-
-namespace {
-
-// Test vectors are taken from Appendix B of
-// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
-
-static const uint8 kKey1[16] = {
-  0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b,
-  0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e,
-};
-
-static const uint8 kCiphertext2[] = {
-  0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
-  0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
-};
-
-static const uint8 kKey3[16] = {
-  0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
-  0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78,
-};
-
-static const uint8 kCiphertext3[] = {
-  0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
-  0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
-  0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
-  0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
-  0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
-  0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
-  0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
-  0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
-};
-
-static const uint8 kAdditional4[] = {
-  0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-  0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-  0xab, 0xad, 0xda, 0xd2,
-};
-
-struct TestCase {
-  const uint8* key;
-  const uint8* additional;
-  unsigned additional_length;
-  const uint8* ciphertext;
-  unsigned ciphertext_length;
-  const uint8 expected[16];
-};
-
-static const TestCase kTestCases[] = {
-  {
-    kKey1,
-    NULL,
-    0,
-    NULL,
-    0,
-    {
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    },
-  },
-  {
-    kKey1,
-    NULL,
-    0,
-    kCiphertext2,
-    sizeof(kCiphertext2),
-    {
-      0xf3, 0x8c, 0xbb, 0x1a, 0xd6, 0x92, 0x23, 0xdc,
-      0xc3, 0x45, 0x7a, 0xe5, 0xb6, 0xb0, 0xf8, 0x85,
-    },
-  },
-  {
-    kKey3,
-    NULL,
-    0,
-    kCiphertext3,
-    sizeof(kCiphertext3),
-    {
-      0x7f, 0x1b, 0x32, 0xb8, 0x1b, 0x82, 0x0d, 0x02,
-      0x61, 0x4f, 0x88, 0x95, 0xac, 0x1d, 0x4e, 0xac,
-    },
-  },
-  {
-    kKey3,
-    kAdditional4,
-    sizeof(kAdditional4),
-    kCiphertext3,
-    sizeof(kCiphertext3) - 4,
-    {
-      0x69, 0x8e, 0x57, 0xf7, 0x0e, 0x6e, 0xcc, 0x7f,
-      0xd9, 0x46, 0x3b, 0x72, 0x60, 0xa9, 0xae, 0x5f,
-    },
-  },
-};
-
-TEST(GaloisHash, TestCases) {
-  uint8 out[16];
-
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
-    const TestCase& test = kTestCases[i];
-
-    GaloisHash hash(test.key);
-    if (test.additional_length)
-      hash.UpdateAdditional(test.additional, test.additional_length);
-    if (test.ciphertext_length)
-      hash.UpdateCiphertext(test.ciphertext, test.ciphertext_length);
-    hash.Finish(out, sizeof(out));
-    EXPECT_TRUE(0 == memcmp(out, test.expected, 16));
-  }
-}
-
-TEST(GaloisHash, TestCasesByteAtATime) {
-  uint8 out[16];
-
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
-    const TestCase& test = kTestCases[i];
-
-    GaloisHash hash(test.key);
-    for (size_t i = 0; i < test.additional_length; ++i)
-      hash.UpdateAdditional(test.additional + i, 1);
-    for (size_t i = 0; i < test.ciphertext_length; ++i)
-      hash.UpdateCiphertext(test.ciphertext + i, 1);
-    hash.Finish(out, sizeof(out));
-    EXPECT_TRUE(0 == memcmp(out, test.expected, 16));
-  }
-}
-
-}  // namespace
-
-}  // namespace crypto
diff --git a/src/crypto/hkdf.cc b/src/crypto/hkdf.cc
new file mode 100644
index 0000000..21698e6
--- /dev/null
+++ b/src/crypto/hkdf.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 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/hkdf.h"
+
+#include <memory>
+
+#include "base/logging.h"
+#include "crypto/hmac.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/hkdf.h"
+
+namespace crypto {
+
+std::string HkdfSha256(base::StringPiece secret,
+                       base::StringPiece salt,
+                       base::StringPiece info,
+                       size_t derived_key_size) {
+  std::string key;
+  key.resize(derived_key_size);
+  int result = ::HKDF(
+      reinterpret_cast<uint8_t*>(&key[0]), derived_key_size, EVP_sha256(),
+      reinterpret_cast<const uint8_t*>(secret.data()), secret.size(),
+      reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
+      reinterpret_cast<const uint8_t*>(info.data()), info.size());
+  DCHECK(result);
+  return key;
+}
+
+}  // namespace crypto
diff --git a/src/crypto/hkdf.h b/src/crypto/hkdf.h
new file mode 100644
index 0000000..7fc4381
--- /dev/null
+++ b/src/crypto/hkdf.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2013 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_HKDF_H_
+#define CRYPTO_HKDF_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "crypto/crypto_export.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+CRYPTO_EXPORT
+std::string HkdfSha256(base::StringPiece secret,
+                       base::StringPiece salt,
+                       base::StringPiece info,
+                       size_t derived_key_size);
+
+}  // namespace crypto
+
+#endif  // CRYPTO_HKDF_H_
diff --git a/src/crypto/hmac.cc b/src/crypto/hmac.cc
index 126d124..dcd0386 100644
--- a/src/crypto/hmac.cc
+++ b/src/crypto/hmac.cc
@@ -5,20 +5,27 @@
 #include "crypto/hmac.h"
 
 #include <algorithm>
+#include <string>
 
 #include "base/logging.h"
+#include "base/stl_util.h"
+#include "crypto/openssl_util.h"
 #include "crypto/secure_util.h"
 #include "crypto/symmetric_key.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/hmac.h"
 
 namespace crypto {
 
-bool HMAC::Init(SymmetricKey* key) {
-  std::string raw_key;
-  bool result = key->GetRawKey(&raw_key) && Init(raw_key);
-  // Zero out key copy.  This might get optimized away, but one can hope.
-  // Using std::string to store key info at all is a larger problem.
-  std::fill(raw_key.begin(), raw_key.end(), 0);
-  return result;
+HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg), initialized_(false) {
+  // Only SHA-1 and SHA-256 hash algorithms are supported now.
+  DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256);
+}
+
+HMAC::~HMAC() {
+  // Zero out key copy.
+  key_.assign(key_.size(), 0);
+  base::STLClearObject(&key_);
 }
 
 size_t HMAC::DigestLength() const {
@@ -33,19 +40,42 @@
   }
 }
 
-bool HMAC::Verify(const base::StringPiece& data,
-                  const base::StringPiece& digest) const {
+bool HMAC::Init(const unsigned char* key, size_t key_length) {
+  // Init must not be called more than once on the same HMAC object.
+  DCHECK(!initialized_);
+  initialized_ = true;
+  key_.assign(key, key + key_length);
+  return true;
+}
+
+bool HMAC::Init(const SymmetricKey* key) {
+  return Init(key->key());
+}
+
+bool HMAC::Sign(base::StringPiece data,
+                unsigned char* digest,
+                size_t digest_length) const {
+  DCHECK(initialized_);
+
+  ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest, digest_length);
+  return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), key_.data(),
+                  key_.size(),
+                  reinterpret_cast<const unsigned char*>(data.data()),
+                  data.size(), result.safe_buffer(), nullptr);
+}
+
+bool HMAC::Verify(base::StringPiece data, base::StringPiece digest) const {
   if (digest.size() != DigestLength())
     return false;
   return VerifyTruncated(data, digest);
 }
 
-bool HMAC::VerifyTruncated(const base::StringPiece& data,
-                           const base::StringPiece& digest) const {
+bool HMAC::VerifyTruncated(base::StringPiece data,
+                           base::StringPiece digest) const {
   if (digest.empty())
     return false;
   size_t digest_length = DigestLength();
-  scoped_array<unsigned char> computed_digest(
+  std::unique_ptr<unsigned char[]> computed_digest(
       new unsigned char[digest_length]);
   if (!Sign(data, computed_digest.get(), digest_length))
     return false;
diff --git a/src/crypto/hmac.h b/src/crypto/hmac.h
index d527d16..608fc4e 100644
--- a/src/crypto/hmac.h
+++ b/src/crypto/hmac.h
@@ -8,16 +8,18 @@
 #ifndef CRYPTO_HMAC_H_
 #define CRYPTO_HMAC_H_
 
-#include "base/basictypes.h"
+#include <memory>
+#include <vector>
+
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_piece.h"
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
 // Simplify the interface and reduce includes by abstracting out the internals.
-struct HMACPlatformData;
 class SymmetricKey;
 
 class CRYPTO_EXPORT HMAC {
@@ -50,11 +52,11 @@
 
   // Initializes this instance using |key|. Call Init
   // only once. It returns false on the second or later calls.
-  bool Init(SymmetricKey* key) WARN_UNUSED_RESULT;
+  bool Init(const SymmetricKey* key) WARN_UNUSED_RESULT;
 
   // Initializes this instance using |key|. Call Init only once. It returns
   // false on the second or later calls.
-  bool Init(const base::StringPiece& key) WARN_UNUSED_RESULT {
+  bool Init(base::StringPiece key) WARN_UNUSED_RESULT {
     return Init(reinterpret_cast<const unsigned char*>(key.data()),
                 key.size());
   }
@@ -62,7 +64,8 @@
   // Calculates the HMAC for the message in |data| using the algorithm supplied
   // to the constructor and the key supplied to the Init method. The HMAC is
   // returned in |digest|, which has |digest_length| bytes of storage available.
-  bool Sign(const base::StringPiece& data, unsigned char* digest,
+  bool Sign(base::StringPiece data,
+            unsigned char* digest,
             size_t digest_length) const WARN_UNUSED_RESULT;
 
   // Verifies that the HMAC for the message in |data| equals the HMAC provided
@@ -72,18 +75,18 @@
   // comparisons may result in side-channel disclosures, such as timing, that
   // undermine the cryptographic integrity. |digest| must be exactly
   // |DigestLength()| bytes long.
-  bool Verify(const base::StringPiece& data,
-              const base::StringPiece& digest) const WARN_UNUSED_RESULT;
+  bool Verify(base::StringPiece data,
+              base::StringPiece digest) const WARN_UNUSED_RESULT;
 
   // Verifies a truncated HMAC, behaving identical to Verify(), except
   // that |digest| is allowed to be smaller than |DigestLength()|.
-  bool VerifyTruncated(
-      const base::StringPiece& data,
-      const base::StringPiece& digest) const WARN_UNUSED_RESULT;
+  bool VerifyTruncated(base::StringPiece data,
+                       base::StringPiece digest) const WARN_UNUSED_RESULT;
 
  private:
   HashAlgorithm hash_alg_;
-  scoped_ptr<HMACPlatformData> plat_;
+  bool initialized_;
+  std::vector<unsigned char> key_;
 
   DISALLOW_COPY_AND_ASSIGN(HMAC);
 };
diff --git a/src/crypto/hmac_openssl.cc b/src/crypto/hmac_openssl.cc
deleted file mode 100644
index 2494d1c..0000000
--- a/src/crypto/hmac_openssl.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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 "crypto/hmac.h"
-
-#include <openssl/hmac.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "crypto/openssl_util.h"
-
-namespace crypto {
-
-struct HMACPlatformData {
-  std::vector<unsigned char> key;
-};
-
-HMAC::HMAC(HashAlgorithm hash_alg)
-    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
-  // Only SHA-1 and SHA-256 hash algorithms are supported now.
-  DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256);
-}
-
-bool HMAC::Init(const unsigned char* key, size_t key_length) {
-  // Init must not be called more than once on the same HMAC object.
-  DCHECK(plat_->key.empty());
-
-  plat_->key.assign(key, key + key_length);
-  return true;
-}
-
-HMAC::~HMAC() {
-  // Zero out key copy.
-  plat_->key.assign(plat_->key.size(), 0);
-  STLClearObject(&plat_->key);
-}
-
-bool HMAC::Sign(const base::StringPiece& data,
-                unsigned char* digest,
-                size_t digest_length) const {
-  DCHECK(!plat_->key.empty());  // Init must be called before Sign.
-
-  ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest, digest_length);
-  return ::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(),
-                &plat_->key[0], plat_->key.size(),
-                reinterpret_cast<const unsigned char*>(data.data()),
-                data.size(),
-                result.safe_buffer(), NULL) != NULL;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/hmac_unittest.cc b/src/crypto/hmac_unittest.cc
index f0844a9..876add1 100644
--- a/src/crypto/hmac_unittest.cc
+++ b/src/crypto/hmac_unittest.cc
@@ -4,7 +4,10 @@
 
 #include <string>
 
+#include "base/macros.h"
 #include "crypto/hmac.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 static const size_t kSHA1DigestSize = 20;
@@ -79,7 +82,8 @@
   unsigned char calculated_hmac[kSHA1DigestSize];
 
   EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
-  EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
+  EXPECT_EQ(0,
+            SbMemoryCompare(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
 }
 
 // Test cases from RFC 2202 section 3
@@ -142,14 +146,14 @@
           "\xBB\xFF\x1A\x91" }
   };
 
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+  for (size_t i = 0; i < arraysize(cases); ++i) {
     crypto::HMAC hmac(crypto::HMAC::SHA1);
     ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key),
                           cases[i].key_len));
     std::string data_string(cases[i].data, cases[i].data_len);
     unsigned char digest[kSHA1DigestSize];
     EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
-    EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize));
+    EXPECT_EQ(0, SbMemoryCompare(cases[i].digest, digest, kSHA1DigestSize));
   }
 }
 
@@ -175,7 +179,8 @@
 
   EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength());
   EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize));
-  EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
+  EXPECT_EQ(
+      0, SbMemoryCompare(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
 }
 
 // Based on NSS's FIPS HMAC power-up self-test.
@@ -216,7 +221,8 @@
 
   EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength());
   EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
-  EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize));
+  EXPECT_EQ(0,
+            SbMemoryCompare(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize));
   EXPECT_TRUE(hmac.Verify(
       message_data,
       base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
@@ -231,7 +237,8 @@
   unsigned char calculated_hmac2[kSHA256DigestSize];
 
   EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize));
-  EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize));
+  EXPECT_EQ(0, SbMemoryCompare(kKnownHMACSHA256, calculated_hmac2,
+                               kSHA256DigestSize));
 }
 
 TEST(HMACTest, HMACObjectReuse) {
@@ -239,12 +246,13 @@
   ASSERT_TRUE(
       hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
                 kSimpleKeyLength));
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSimpleHmacCases); ++i) {
+  for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) {
     std::string data_string(kSimpleHmacCases[i].data,
                             kSimpleHmacCases[i].data_len);
     unsigned char digest[kSHA1DigestSize];
     EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
-    EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize));
+    EXPECT_EQ(0, SbMemoryCompare(kSimpleHmacCases[i].digest, digest,
+                                 kSHA1DigestSize));
   }
 }
 
@@ -254,7 +262,7 @@
       hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
                 kSimpleKeyLength));
   const char empty_digest[kSHA1DigestSize] = { 0 };
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSimpleHmacCases); ++i) {
+  for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) {
     // Expected results
     EXPECT_TRUE(hmac.Verify(
         base::StringPiece(kSimpleHmacCases[i].data,
@@ -275,3 +283,21 @@
         base::StringPiece(empty_digest, kSHA1DigestSize)));
   }
 }
+
+TEST(HMACTest, EmptyKey) {
+  // Test vector from https://en.wikipedia.org/wiki/HMAC
+  const char* kExpectedDigest =
+      "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63"
+      "\x70\x69\x0E\x1D";
+  base::StringPiece data("");
+
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(hmac.Init(nullptr, 0));
+
+  unsigned char digest[kSHA1DigestSize];
+  EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize));
+  EXPECT_EQ(0, SbMemoryCompare(kExpectedDigest, digest, kSHA1DigestSize));
+
+  EXPECT_TRUE(hmac.Verify(
+      data, base::StringPiece(kExpectedDigest, kSHA1DigestSize)));
+}
diff --git a/src/crypto/mac_security_services_lock.cc b/src/crypto/mac_security_services_lock.cc
new file mode 100644
index 0000000..a9a70cd
--- /dev/null
+++ b/src/crypto/mac_security_services_lock.cc
@@ -0,0 +1,42 @@
+// 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 "crypto/mac_security_services_lock.h"
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+
+namespace {
+
+class SecurityServicesSingleton {
+ public:
+  static SecurityServicesSingleton* GetInstance() {
+    return base::Singleton<
+        SecurityServicesSingleton,
+        base::LeakySingletonTraits<SecurityServicesSingleton>>::get();
+  }
+
+  base::Lock& lock() { return lock_; }
+
+ private:
+  friend struct base::DefaultSingletonTraits<SecurityServicesSingleton>;
+
+  SecurityServicesSingleton() {}
+  ~SecurityServicesSingleton() {}
+
+  base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(SecurityServicesSingleton);
+};
+
+}  // namespace
+
+namespace crypto {
+
+base::Lock& GetMacSecurityServicesLock() {
+  return SecurityServicesSingleton::GetInstance()->lock();
+}
+
+}  // namespace crypto
diff --git a/src/crypto/mac_security_services_lock.h b/src/crypto/mac_security_services_lock.h
new file mode 100644
index 0000000..fe56c6f
--- /dev/null
+++ b/src/crypto/mac_security_services_lock.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 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_MAC_SECURITY_SERVICES_LOCK_H_
+#define CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_
+
+#include "crypto/crypto_export.h"
+
+namespace base {
+class Lock;
+}
+
+namespace crypto {
+
+// The Mac OS X certificate and key management wrappers over CSSM are not
+// thread-safe. In particular, code that accesses the CSSM database is
+// problematic.
+//
+// http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html
+CRYPTO_EXPORT base::Lock& GetMacSecurityServicesLock();
+
+}  // namespace crypto
+
+#endif  // CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_
diff --git a/src/crypto/mock_apple_keychain.cc b/src/crypto/mock_apple_keychain.cc
new file mode 100644
index 0000000..453114e
--- /dev/null
+++ b/src/crypto/mock_apple_keychain.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2012 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/mock_apple_keychain.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+
+namespace {
+
+// Adds an entry to a local histogram to indicate that the Apple Keychain would
+// have been accessed, if this class were not a mock of the Apple Keychain.
+void IncrementKeychainAccessHistogram() {
+  // This local histogram is accessed by Telemetry to track the number of times
+  // the keychain is accessed, since keychain access is known to be synchronous
+  // and slow.
+  LOCAL_HISTOGRAM_BOOLEAN("OSX.Keychain.Access", true);
+}
+
+}  // namespace
+
+namespace crypto {
+
+OSStatus MockAppleKeychain::FindGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32* passwordLength,
+    void** passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  IncrementKeychainAccessHistogram();
+
+  // When simulating |noErr|, return canned |passwordData| and
+  // |passwordLength|.  Otherwise, just return given code.
+  if (find_generic_result_ == noErr) {
+    static const char kPassword[] = "my_password";
+    DCHECK(passwordData);
+    // The function to free this data is mocked so the cast is fine.
+    *passwordData = const_cast<char*>(kPassword);
+    DCHECK(passwordLength);
+    *passwordLength = arraysize(kPassword);
+    password_data_count_++;
+  }
+
+  return find_generic_result_;
+}
+
+OSStatus MockAppleKeychain::ItemFreeContent(void* data) const {
+  // No-op.
+  password_data_count_--;
+  return noErr;
+}
+
+OSStatus MockAppleKeychain::AddGenericPassword(
+    UInt32 serviceNameLength,
+    const char* serviceName,
+    UInt32 accountNameLength,
+    const char* accountName,
+    UInt32 passwordLength,
+    const void* passwordData,
+    AppleSecKeychainItemRef* itemRef) const {
+  IncrementKeychainAccessHistogram();
+
+  called_add_generic_ = true;
+
+  DCHECK_GT(passwordLength, 0U);
+  DCHECK(passwordData);
+  return noErr;
+}
+
+std::string MockAppleKeychain::GetEncryptionPassword() const {
+  IncrementKeychainAccessHistogram();
+  return "mock_password";
+}
+
+}  // namespace crypto
diff --git a/src/crypto/mock_apple_keychain.h b/src/crypto/mock_apple_keychain.h
new file mode 100644
index 0000000..1770026
--- /dev/null
+++ b/src/crypto/mock_apple_keychain.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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_MOCK_APPLE_KEYCHAIN_H_
+#define CRYPTO_MOCK_APPLE_KEYCHAIN_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "crypto/apple_keychain.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+// Mock Keychain wrapper for testing code that interacts with the OS X
+// Keychain.
+//
+// Note that "const" is pretty much meaningless for this class; the const-ness
+// of AppleKeychain doesn't apply to the actual keychain data, so all of the
+// Mock data is mutable; don't assume that it won't change over the life of
+// tests.
+class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
+ public:
+  MockAppleKeychain();
+  ~MockAppleKeychain() override;
+
+  // AppleKeychain implementation.
+  OSStatus FindGenericPassword(UInt32 serviceNameLength,
+                               const char* serviceName,
+                               UInt32 accountNameLength,
+                               const char* accountName,
+                               UInt32* passwordLength,
+                               void** passwordData,
+                               AppleSecKeychainItemRef* itemRef) const override;
+  OSStatus ItemFreeContent(void* data) const override;
+  OSStatus AddGenericPassword(UInt32 serviceNameLength,
+                              const char* serviceName,
+                              UInt32 accountNameLength,
+                              const char* accountName,
+                              UInt32 passwordLength,
+                              const void* passwordData,
+                              AppleSecKeychainItemRef* itemRef) const override;
+
+  // Returns the password that OSCrypt uses to generate its encryption key.
+  std::string GetEncryptionPassword() const;
+
+#if !defined(OS_IOS)
+  OSStatus ItemDelete(SecKeychainItemRef itemRef) const override;
+#endif  // !defined(OS_IOS)
+
+  // |FindGenericPassword()| can return different results depending on user
+  // interaction with the system Keychain.  For mocking purposes we allow the
+  // user of this class to specify the result code of the
+  // |FindGenericPassword()| call so we can simulate the result of different
+  // user interactions.
+  void set_find_generic_result(OSStatus result) {
+    find_generic_result_ = result;
+  }
+
+  // Returns the true if |AddGenericPassword()| was called.
+  bool called_add_generic() const { return called_add_generic_; }
+
+  // Returns the number of allocations - deallocations for password data.
+  int password_data_count() const { return password_data_count_; }
+
+ private:
+  // Result code for the |FindGenericPassword()| method.
+  OSStatus find_generic_result_;
+
+  // Records whether |AddGenericPassword()| gets called.
+  mutable bool called_add_generic_;
+
+  // Tracks the allocations and frees of password data in |FindGenericPassword|
+  // and |ItemFreeContent|.
+  mutable int password_data_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockAppleKeychain);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_MOCK_APPLE_KEYCHAIN_H_
diff --git a/src/crypto/mock_apple_keychain_ios.cc b/src/crypto/mock_apple_keychain_ios.cc
index f94a80d..9e8a164 100644
--- a/src/crypto/mock_apple_keychain_ios.cc
+++ b/src/crypto/mock_apple_keychain_ios.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/time/time.h"
 #include "crypto/mock_apple_keychain.h"
 
 namespace crypto {
diff --git a/src/crypto/mock_apple_keychain_mac.cc b/src/crypto/mock_apple_keychain_mac.cc
index 181f108..036459a 100644
--- a/src/crypto/mock_apple_keychain_mac.cc
+++ b/src/crypto/mock_apple_keychain_mac.cc
@@ -3,507 +3,22 @@
 // found in the LICENSE file.
 
 #include "base/logging.h"
-#include "base/time.h"
+#include "base/macros.h"
+#include "base/time/time.h"
 #include "crypto/mock_apple_keychain.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
-// static
-const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef =
-    reinterpret_cast<SecKeychainSearchRef>(1000);
-
 MockAppleKeychain::MockAppleKeychain()
-    : next_item_key_(0),
-      search_copy_count_(0),
-      keychain_item_copy_count_(0),
-      attribute_data_copy_count_(0),
-      find_generic_result_(noErr),
+    : find_generic_result_(noErr),
       called_add_generic_(false),
       password_data_count_(0) {}
 
-void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const {
-  UInt32 tags[] = { kSecAccountItemAttr,
-                    kSecServerItemAttr,
-                    kSecPortItemAttr,
-                    kSecPathItemAttr,
-                    kSecProtocolItemAttr,
-                    kSecAuthenticationTypeItemAttr,
-                    kSecSecurityDomainItemAttr,
-                    kSecCreationDateItemAttr,
-                    kSecNegativeItemAttr,
-                    kSecCreatorItemAttr };
-  keychain_attr_list_[key] = SecKeychainAttributeList();
-  keychain_data_[key] = KeychainPasswordData();
-  keychain_attr_list_[key].count = arraysize(tags);
-  keychain_attr_list_[key].attr = static_cast<SecKeychainAttribute*>(
-      calloc(keychain_attr_list_[key].count, sizeof(SecKeychainAttribute)));
-  for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) {
-    keychain_attr_list_[key].attr[i].tag = tags[i];
-    size_t data_size = 0;
-    switch (tags[i]) {
-      case kSecPortItemAttr:
-        data_size = sizeof(UInt32);
-        break;
-      case kSecProtocolItemAttr:
-        data_size = sizeof(SecProtocolType);
-        break;
-      case kSecAuthenticationTypeItemAttr:
-        data_size = sizeof(SecAuthenticationType);
-        break;
-      case kSecNegativeItemAttr:
-        data_size = sizeof(Boolean);
-        break;
-      case kSecCreatorItemAttr:
-        data_size = sizeof(OSType);
-        break;
-    }
-    if (data_size > 0) {
-      keychain_attr_list_[key].attr[i].length = data_size;
-      keychain_attr_list_[key].attr[i].data = calloc(1, data_size);
-    }
-  }
-}
+MockAppleKeychain::~MockAppleKeychain() {}
 
-MockAppleKeychain::~MockAppleKeychain() {
-  for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin();
-       it != keychain_attr_list_.end();
-       ++it) {
-    for (unsigned int i = 0; i < it->second.count; ++i) {
-      if (it->second.attr[i].data)
-        free(it->second.attr[i].data);
-    }
-    free(it->second.attr);
-    if (keychain_data_[it->first].data)
-      free(keychain_data_[it->first].data);
-  }
-  keychain_attr_list_.clear();
-  keychain_data_.clear();
-}
-
-SecKeychainAttribute* MockAppleKeychain::AttributeWithTag(
-    const SecKeychainAttributeList& attribute_list,
-    UInt32 tag) {
-  int attribute_index = -1;
-  for (unsigned int i = 0; i < attribute_list.count; ++i) {
-    if (attribute_list.attr[i].tag == tag) {
-      attribute_index = i;
-      break;
-    }
-  }
-  if (attribute_index == -1) {
-    NOTREACHED() << "Unsupported attribute: " << tag;
-    return NULL;
-  }
-  return &(attribute_list.attr[attribute_index]);
-}
-
-void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item,
-                                         UInt32 tag,
-                                         const void* data,
-                                         size_t length) {
-  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
-                                                     tag);
-  attribute->length = length;
-  if (length > 0) {
-    if (attribute->data)
-      free(attribute->data);
-    attribute->data = malloc(length);
-    CHECK(attribute->data);
-    memcpy(attribute->data, data, length);
-  } else {
-    attribute->data = NULL;
-  }
-}
-
-void MockAppleKeychain::SetTestDataString(MockKeychainItemType item,
-                                          UInt32 tag,
-                                          const char* value) {
-  SetTestDataBytes(item, tag, value, value ? strlen(value) : 0);
-}
-
-void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item,
-                                        UInt32 value) {
-  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
-                                                     kSecPortItemAttr);
-  UInt32* data = static_cast<UInt32*>(attribute->data);
-  *data = value;
-}
-
-void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item,
-                                            SecProtocolType value) {
-  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
-                                                     kSecProtocolItemAttr);
-  SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data);
-  *data = value;
-}
-
-void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item,
-                                            SecAuthenticationType value) {
-  SecKeychainAttribute* attribute = AttributeWithTag(
-      keychain_attr_list_[item], kSecAuthenticationTypeItemAttr);
-  SecAuthenticationType* data = static_cast<SecAuthenticationType*>(
-      attribute->data);
-  *data = value;
-}
-
-void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item,
-                                                Boolean value) {
-  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
-                                                     kSecNegativeItemAttr);
-  Boolean* data = static_cast<Boolean*>(attribute->data);
-  *data = value;
-}
-
-void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item,
-                                           OSType value) {
-  SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
-                                                     kSecCreatorItemAttr);
-  OSType* data = static_cast<OSType*>(attribute->data);
-  *data = value;
-}
-
-void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item,
-                                                 const void* data,
-                                                 size_t length) {
-  keychain_data_[item].length = length;
-  if (length > 0) {
-    if (keychain_data_[item].data)
-      free(keychain_data_[item].data);
-    keychain_data_[item].data = malloc(length);
-    memcpy(keychain_data_[item].data, data, length);
-  } else {
-    keychain_data_[item].data = NULL;
-  }
-}
-
-void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item,
-                                                  const char* value) {
-  SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0);
-}
-
-OSStatus MockAppleKeychain::ItemCopyAttributesAndData(
-    SecKeychainItemRef itemRef,
-    SecKeychainAttributeInfo* info,
-    SecItemClass* itemClass,
-    SecKeychainAttributeList** attrList,
-    UInt32* length,
-    void** outData) const {
-  DCHECK(itemRef);
-  MockKeychainItemType key =
-      reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
-  if (keychain_attr_list_.find(key) == keychain_attr_list_.end())
-    return errSecInvalidItemRef;
-
-  DCHECK(!itemClass);  // itemClass not implemented in the Mock.
-  if (attrList)
-    *attrList  = &(keychain_attr_list_[key]);
-  if (outData) {
-    *outData = keychain_data_[key].data;
-    DCHECK(length);
-    *length = keychain_data_[key].length;
-  }
-
-  ++attribute_data_copy_count_;
+OSStatus MockAppleKeychain::ItemDelete(AppleSecKeychainItemRef itemRef) const {
   return noErr;
 }
 
-OSStatus MockAppleKeychain::ItemModifyAttributesAndData(
-    SecKeychainItemRef itemRef,
-    const SecKeychainAttributeList* attrList,
-    UInt32 length,
-    const void* data) const {
-  DCHECK(itemRef);
-  const char* fail_trigger = "fail_me";
-  if (length == strlen(fail_trigger) &&
-      memcmp(data, fail_trigger, length) == 0) {
-    return errSecAuthFailed;
-  }
-
-  MockKeychainItemType key =
-      reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
-  if (keychain_attr_list_.find(key) == keychain_attr_list_.end())
-    return errSecInvalidItemRef;
-
-  MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
-  if (attrList) {
-    for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) {
-      if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) {
-        void* data = attrList->attr[change_attr].data;
-        mutable_this->SetTestDataCreator(key, *(static_cast<OSType*>(data)));
-      } else {
-        NOTIMPLEMENTED();
-      }
-    }
-  }
-  if (data)
-    mutable_this->SetTestDataPasswordBytes(key, data, length);
-  return noErr;
-}
-
-OSStatus MockAppleKeychain::ItemFreeAttributesAndData(
-    SecKeychainAttributeList* attrList,
-    void* data) const {
-  --attribute_data_copy_count_;
-  return noErr;
-}
-
-OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
-  MockKeychainItemType key =
-      reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
-
-  for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) {
-    if (keychain_attr_list_[key].attr[i].data)
-      free(keychain_attr_list_[key].attr[i].data);
-  }
-  free(keychain_attr_list_[key].attr);
-  if (keychain_data_[key].data)
-    free(keychain_data_[key].data);
-
-  keychain_attr_list_.erase(key);
-  keychain_data_.erase(key);
-  added_via_api_.erase(key);
-  return noErr;
-}
-
-OSStatus MockAppleKeychain::SearchCreateFromAttributes(
-    CFTypeRef keychainOrArray,
-    SecItemClass itemClass,
-    const SecKeychainAttributeList* attrList,
-    SecKeychainSearchRef* searchRef) const {
-  // Figure out which of our mock items matches, and set up the array we'll use
-  // to generate results out of SearchCopyNext.
-  remaining_search_results_.clear();
-  for (MockKeychainAttributesMap::const_iterator it =
-           keychain_attr_list_.begin();
-       it != keychain_attr_list_.end();
-       ++it) {
-    bool mock_item_matches = true;
-    for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) {
-      SecKeychainAttribute* mock_attribute =
-          AttributeWithTag(it->second, attrList->attr[search_attr].tag);
-      if (mock_attribute->length != attrList->attr[search_attr].length ||
-          memcmp(mock_attribute->data, attrList->attr[search_attr].data,
-                 attrList->attr[search_attr].length) != 0) {
-        mock_item_matches = false;
-        break;
-      }
-    }
-    if (mock_item_matches)
-      remaining_search_results_.push_back(it->first);
-  }
-
-  DCHECK(searchRef);
-  *searchRef = kDummySearchRef;
-  ++search_copy_count_;
-  return noErr;
-}
-
-bool MockAppleKeychain::AlreadyContainsInternetPassword(
-    UInt32 serverNameLength,
-    const char* serverName,
-    UInt32 securityDomainLength,
-    const char* securityDomain,
-    UInt32 accountNameLength,
-    const char* accountName,
-    UInt32 pathLength,
-    const char* path,
-    UInt16 port,
-    SecProtocolType protocol,
-    SecAuthenticationType authenticationType) const {
-  for (MockKeychainAttributesMap::const_iterator it =
-           keychain_attr_list_.begin();
-       it != keychain_attr_list_.end();
-       ++it) {
-    SecKeychainAttribute* attribute;
-    attribute = AttributeWithTag(it->second, kSecServerItemAttr);
-    if ((attribute->length != serverNameLength) ||
-        (attribute->data == NULL && *serverName != '\0') ||
-        (attribute->data != NULL && *serverName == '\0') ||
-        strncmp(serverName,
-                (const char*) attribute->data,
-                serverNameLength) != 0) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecSecurityDomainItemAttr);
-    if ((attribute->length != securityDomainLength) ||
-        (attribute->data == NULL && *securityDomain != '\0') ||
-        (attribute->data != NULL && *securityDomain == '\0') ||
-        strncmp(securityDomain,
-                (const char*) attribute->data,
-                securityDomainLength) != 0) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecAccountItemAttr);
-    if ((attribute->length != accountNameLength) ||
-        (attribute->data == NULL && *accountName != '\0') ||
-        (attribute->data != NULL && *accountName == '\0') ||
-        strncmp(accountName,
-                (const char*) attribute->data,
-                accountNameLength) != 0) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecPathItemAttr);
-    if ((attribute->length != pathLength) ||
-        (attribute->data == NULL && *path != '\0') ||
-        (attribute->data != NULL && *path == '\0') ||
-        strncmp(path,
-                (const char*) attribute->data,
-                pathLength) != 0) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecPortItemAttr);
-    if ((attribute->data == NULL) ||
-        (port != *(static_cast<UInt32*>(attribute->data)))) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecProtocolItemAttr);
-    if ((attribute->data == NULL) ||
-        (protocol != *(static_cast<SecProtocolType*>(attribute->data)))) {
-      continue;
-    }
-    attribute = AttributeWithTag(it->second, kSecAuthenticationTypeItemAttr);
-    if ((attribute->data == NULL) ||
-        (authenticationType !=
-            *(static_cast<SecAuthenticationType*>(attribute->data)))) {
-      continue;
-    }
-    // The keychain already has this item, since all fields other than the
-    // password match.
-    return true;
-  }
-  return false;
-}
-
-OSStatus MockAppleKeychain::AddInternetPassword(
-    SecKeychainRef keychain,
-    UInt32 serverNameLength,
-    const char* serverName,
-    UInt32 securityDomainLength,
-    const char* securityDomain,
-    UInt32 accountNameLength,
-    const char* accountName,
-    UInt32 pathLength,
-    const char* path,
-    UInt16 port,
-    SecProtocolType protocol,
-    SecAuthenticationType authenticationType,
-    UInt32 passwordLength,
-    const void* passwordData,
-    SecKeychainItemRef* itemRef) const {
-
-  // Check for the magic duplicate item trigger.
-  if (strcmp(serverName, "some.domain.com") == 0)
-    return errSecDuplicateItem;
-
-  // If the account already exists in the keychain, we don't add it.
-  if (AlreadyContainsInternetPassword(serverNameLength, serverName,
-                                      securityDomainLength, securityDomain,
-                                      accountNameLength, accountName,
-                                      pathLength, path,
-                                      port, protocol,
-                                      authenticationType)) {
-    return errSecDuplicateItem;
-  }
-
-  // Pick the next unused slot.
-  MockKeychainItemType key = next_item_key_++;
-
-  // Initialize keychain data storage at the target location.
-  InitializeKeychainData(key);
-
-  MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
-  mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName,
-                                 serverNameLength);
-  mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr,
-                                 securityDomain, securityDomainLength);
-  mutable_this->SetTestDataBytes(key, kSecAccountItemAttr, accountName,
-                                 accountNameLength);
-  mutable_this->SetTestDataBytes(key, kSecPathItemAttr, path, pathLength);
-  mutable_this->SetTestDataPort(key, port);
-  mutable_this->SetTestDataProtocol(key, protocol);
-  mutable_this->SetTestDataAuthType(key, authenticationType);
-  mutable_this->SetTestDataPasswordBytes(key, passwordData,
-                                         passwordLength);
-  base::Time::Exploded exploded_time;
-  base::Time::Now().UTCExplode(&exploded_time);
-  char time_string[128];
-  snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ",
-           exploded_time.year, exploded_time.month, exploded_time.day_of_month,
-           exploded_time.hour, exploded_time.minute, exploded_time.second);
-  mutable_this->SetTestDataString(key, kSecCreationDateItemAttr, time_string);
-
-  added_via_api_.insert(key);
-
-  if (itemRef) {
-    *itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1);
-    ++keychain_item_copy_count_;
-  }
-  return noErr;
-}
-
-OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
-                                           SecKeychainItemRef* itemRef) const {
-  if (remaining_search_results_.empty())
-    return errSecItemNotFound;
-  MockKeychainItemType key = remaining_search_results_.front();
-  remaining_search_results_.erase(remaining_search_results_.begin());
-  *itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1);
-  ++keychain_item_copy_count_;
-  return noErr;
-}
-
-void MockAppleKeychain::Free(CFTypeRef ref) const {
-  if (!ref)
-    return;
-
-  if (ref == kDummySearchRef) {
-    --search_copy_count_;
-  } else {
-    --keychain_item_copy_count_;
-  }
-}
-
-int MockAppleKeychain::UnfreedSearchCount() const {
-  return search_copy_count_;
-}
-
-int MockAppleKeychain::UnfreedKeychainItemCount() const {
-  return keychain_item_copy_count_;
-}
-
-int MockAppleKeychain::UnfreedAttributeDataCount() const {
-  return attribute_data_copy_count_;
-}
-
-bool MockAppleKeychain::CreatorCodesSetForAddedItems() const {
-  for (std::set<MockKeychainItemType>::const_iterator
-           i = added_via_api_.begin();
-       i != added_via_api_.end();
-       ++i) {
-    SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i],
-                                                       kSecCreatorItemAttr);
-    OSType* data = static_cast<OSType*>(attribute->data);
-    if (*data == 0)
-      return false;
-  }
-  return true;
-}
-
-void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) {
-  MockKeychainItemType key = next_item_key_++;
-
-  InitializeKeychainData(key);
-  SetTestDataAuthType(key, item_data.auth_type);
-  SetTestDataString(key, kSecServerItemAttr, item_data.server);
-  SetTestDataProtocol(key, item_data.protocol);
-  SetTestDataString(key, kSecPathItemAttr, item_data.path);
-  SetTestDataPort(key, item_data.port);
-  SetTestDataString(key, kSecSecurityDomainItemAttr,
-                    item_data.security_domain);
-  SetTestDataString(key, kSecCreationDateItemAttr, item_data.creation_date);
-  SetTestDataString(key, kSecAccountItemAttr, item_data.username);
-  SetTestDataPasswordString(key, item_data.password);
-  SetTestDataNegativeItem(key, item_data.negative_item);
-}
-
 }  // namespace crypto
diff --git a/src/crypto/nss_crypto_module_delegate.h b/src/crypto/nss_crypto_module_delegate.h
new file mode 100644
index 0000000..cb87070
--- /dev/null
+++ b/src/crypto/nss_crypto_module_delegate.h
@@ -0,0 +1,46 @@
+// Copyright 2013 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_NSS_CRYPTO_MODULE_DELEGATE_H_
+#define CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+
+namespace crypto {
+
+// PK11_SetPasswordFunc is a global setting.  An implementation of
+// CryptoModuleBlockingPasswordDelegate should be passed using wincx() as the
+// user data argument (|wincx|) to relevant NSS functions, which the global
+// password handler will call to do the actual work. This delegate should only
+// be used in NSS calls on worker threads due to the blocking nature.
+class CryptoModuleBlockingPasswordDelegate
+    : public base::RefCountedThreadSafe<CryptoModuleBlockingPasswordDelegate> {
+ public:
+
+  // Return a value suitable for passing to the |wincx| argument of relevant NSS
+  // functions. This should be used instead of passing the object pointer
+  // directly to avoid accidentally casting a pointer to a subclass to void* and
+  // then casting back to a pointer of the base class
+  void* wincx() { return this; }
+
+  // Requests a password to unlock |slot_name|. The interface is synchronous
+  // because NSS cannot issue an asynchronous request. |retry| is true if this
+  // is a request for the retry and we previously returned the wrong password.
+  // The implementation should set |*cancelled| to true if the user cancelled
+  // instead of entering a password, otherwise it should return the password the
+  // user entered.
+  virtual std::string RequestPassword(const std::string& slot_name, bool retry,
+                                      bool* cancelled) = 0;
+
+ protected:
+  friend class base::RefCountedThreadSafe<CryptoModuleBlockingPasswordDelegate>;
+
+  virtual ~CryptoModuleBlockingPasswordDelegate() {}
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
diff --git a/src/crypto/nss_key_util.cc b/src/crypto/nss_key_util.cc
new file mode 100644
index 0000000..5b43743
--- /dev/null
+++ b/src/crypto/nss_key_util.cc
@@ -0,0 +1,154 @@
+// 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/nss_key_util.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <secmod.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+namespace {
+
+struct PublicKeyInfoDeleter {
+  inline void operator()(CERTSubjectPublicKeyInfo* spki) {
+    SECKEY_DestroySubjectPublicKeyInfo(spki);
+  }
+};
+
+typedef std::unique_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
+    ScopedPublicKeyInfo;
+
+// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing
+// the CKA_ID of that public key or nullptr on error.
+ScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t>& input) {
+  // First, decode and save the public key.
+  SECItem key_der;
+  key_der.type = siBuffer;
+  key_der.data = const_cast<unsigned char*>(input.data());
+  key_der.len = input.size();
+
+  ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
+  if (!spki)
+    return nullptr;
+
+  ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
+  if (!result)
+    return nullptr;
+
+  // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are
+  // supported.
+  if (SECKEY_GetPublicKeyType(result.get()) != rsaKey)
+    return nullptr;
+
+  return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus));
+}
+
+}  // namespace
+
+bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot,
+                           uint16_t num_bits,
+                           bool permanent,
+                           ScopedSECKEYPublicKey* public_key,
+                           ScopedSECKEYPrivateKey* private_key) {
+  DCHECK(slot);
+
+  PK11RSAGenParams param;
+  param.keySizeInBits = num_bits;
+  param.pe = 65537L;
+  SECKEYPublicKey* public_key_raw = nullptr;
+  private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+                                          &param, &public_key_raw, permanent,
+                                          permanent /* sensitive */, nullptr));
+  if (!*private_key)
+    return false;
+
+  public_key->reset(public_key_raw);
+  return true;
+}
+
+ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo(
+    PK11SlotInfo* slot,
+    const std::vector<uint8_t>& input,
+    bool permanent) {
+  DCHECK(slot);
+
+  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+  DCHECK(arena);
+
+  // Excess data is illegal, but NSS silently accepts it, so first ensure that
+  // |input| consists of a single ASN.1 element.
+  SECItem input_item;
+  input_item.data = const_cast<unsigned char*>(input.data());
+  input_item.len = input.size();
+  SECItem der_private_key_info;
+  SECStatus rv =
+      SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info,
+                             SEC_ASN1_GET(SEC_AnyTemplate), &input_item);
+  if (rv != SECSuccess)
+    return nullptr;
+
+  // Allow the private key to be used for key unwrapping, data decryption,
+  // and signature generation.
+  const unsigned int key_usage =
+      KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
+  SECKEYPrivateKey* key_raw = nullptr;
+  rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+      slot, &der_private_key_info, nullptr, nullptr, permanent,
+      permanent /* sensitive */, key_usage, &key_raw, nullptr);
+  if (rv != SECSuccess)
+    return nullptr;
+  return ScopedSECKEYPrivateKey(key_raw);
+}
+
+ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo(
+    const std::vector<uint8_t>& input) {
+  EnsureNSSInit();
+
+  ScopedSECItem cka_id(MakeIDFromSPKI(input));
+  if (!cka_id)
+    return nullptr;
+
+  // Search all slots in all modules for the key with the given ID.
+  AutoSECMODListReadLock auto_lock;
+  const SECMODModuleList* head = SECMOD_GetDefaultModuleList();
+  for (const SECMODModuleList* item = head; item != nullptr;
+       item = item->next) {
+    int slot_count = item->module->loaded ? item->module->slotCount : 0;
+    for (int i = 0; i < slot_count; i++) {
+      // Look for the key in slot |i|.
+      ScopedSECKEYPrivateKey key(
+          PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr));
+      if (key)
+        return key;
+    }
+  }
+
+  // The key wasn't found in any module.
+  return nullptr;
+}
+
+ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot(
+    const std::vector<uint8_t>& input,
+    PK11SlotInfo* slot) {
+  DCHECK(slot);
+
+  ScopedSECItem cka_id(MakeIDFromSPKI(input));
+  if (!cka_id)
+    return nullptr;
+
+  return ScopedSECKEYPrivateKey(
+      PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr));
+}
+
+}  // namespace crypto
diff --git a/src/crypto/nss_key_util.h b/src/crypto/nss_key_util.h
new file mode 100644
index 0000000..da2d271
--- /dev/null
+++ b/src/crypto/nss_key_util.h
@@ -0,0 +1,53 @@
+// 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_NSS_KEY_UTIL_H_
+#define CRYPTO_NSS_KEY_UTIL_H_
+
+#include <vector>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+#include "starboard/types.h"
+
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+
+namespace crypto {
+
+// Generates a new RSA keypair of size |num_bits| in |slot|. Returns true on
+// success and false on failure. If |permanent| is true, the resulting key is
+// permanent and is not exportable in plaintext form.
+CRYPTO_EXPORT bool GenerateRSAKeyPairNSS(
+    PK11SlotInfo* slot,
+    uint16_t num_bits,
+    bool permanent,
+    ScopedSECKEYPublicKey* out_public_key,
+    ScopedSECKEYPrivateKey* out_private_key);
+
+// Imports a private key from |input| into |slot|. |input| is interpreted as a
+// DER-encoded PrivateKeyInfo block from PKCS #8. Returns nullptr on error. If
+// |permanent| is true, the resulting key is permanent and is not exportable in
+// plaintext form.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+ImportNSSKeyFromPrivateKeyInfo(PK11SlotInfo* slot,
+                               const std::vector<uint8_t>& input,
+                               bool permanent);
+
+// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for
+// the private key half in the key database. Returns the private key on success
+// or nullptr on error.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+FindNSSKeyFromPublicKeyInfo(const std::vector<uint8_t>& input);
+
+// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for
+// the private key half in the slot specified by |slot|. Returns the private key
+// on success or nullptr on error.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+FindNSSKeyFromPublicKeyInfoInSlot(const std::vector<uint8_t>& input,
+                                  PK11SlotInfo* slot);
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_KEY_UTIL_H_
diff --git a/src/crypto/nss_key_util_unittest.cc b/src/crypto/nss_key_util_unittest.cc
new file mode 100644
index 0000000..874fa98
--- /dev/null
+++ b/src/crypto/nss_key_util_unittest.cc
@@ -0,0 +1,86 @@
+// 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/nss_key_util.h"
+
+#include <keyhi.h>
+#include <pk11pub.h>
+
+#include <vector>
+
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "starboard/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+class NSSKeyUtilTest : public testing::Test {
+ public:
+  void SetUp() override {
+    EnsureNSSInit();
+
+    internal_slot_.reset(PK11_GetInternalSlot());
+    ASSERT_TRUE(internal_slot_);
+  }
+
+  PK11SlotInfo* internal_slot() { return internal_slot_.get(); }
+
+ private:
+  ScopedPK11Slot internal_slot_;
+};
+
+TEST_F(NSSKeyUtilTest, GenerateRSAKeyPairNSS) {
+  const int kKeySizeBits = 1024;
+
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), kKeySizeBits,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  EXPECT_EQ(rsaKey, SECKEY_GetPublicKeyType(public_key.get()));
+  EXPECT_EQ(rsaKey, SECKEY_GetPrivateKeyType(private_key.get()));
+  EXPECT_EQ((kKeySizeBits + 7) / 8,
+            PK11_GetPrivateModulusLen(private_key.get()));
+}
+
+TEST_F(NSSKeyUtilTest, FindNSSKeyFromPublicKeyInfo) {
+  // Create an NSS keypair, which will put the keys in the user's NSSDB.
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get()));
+  ASSERT_TRUE(item);
+  std::vector<uint8_t> public_key_der(item->data, item->data + item->len);
+
+  ScopedSECKEYPrivateKey private_key2 =
+      FindNSSKeyFromPublicKeyInfo(public_key_der);
+  ASSERT_TRUE(private_key2);
+  EXPECT_EQ(private_key->pkcs11ID, private_key2->pkcs11ID);
+}
+
+TEST_F(NSSKeyUtilTest, FailedFindNSSKeyFromPublicKeyInfo) {
+  // Create an NSS keypair, which will put the keys in the user's NSSDB.
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get()));
+  ASSERT_TRUE(item);
+  std::vector<uint8_t> public_key_der(item->data, item->data + item->len);
+
+  // Remove the keys from the DB, and make sure we can't find them again.
+  PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID);
+  PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID);
+
+  EXPECT_FALSE(FindNSSKeyFromPublicKeyInfo(public_key_der));
+}
+
+}  // namespace crypto
diff --git a/src/crypto/nss_util.cc b/src/crypto/nss_util.cc
new file mode 100644
index 0000000..1416529
--- /dev/null
+++ b/src/crypto/nss_util.cc
@@ -0,0 +1,907 @@
+// Copyright (c) 2012 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/nss_util.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <plarena.h>
+#include <prerror.h>
+#include <prinit.h>
+#include <prtime.h>
+#include <secmod.h>
+
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "starboard/types.h"
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/debug/alias.h"
+#include "base/debug/stack_trace.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/path_service.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/thread_checker.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "crypto/nss_crypto_module_delegate.h"
+#include "crypto/nss_util_internal.h"
+
+#if defined(OS_CHROMEOS)
+#include <dlfcn.h>
+#endif
+
+namespace crypto {
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+const char kUserNSSDatabaseName[] = "UserNSSDB";
+
+// Constants for loading the Chrome OS TPM-backed PKCS #11 library.
+const char kChapsModuleName[] = "Chaps";
+const char kChapsPath[] = "libchaps.so";
+
+// Fake certificate authority database used for testing.
+static const base::FilePath::CharType kReadOnlyCertDB[] =
+    FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
+#endif  // defined(OS_CHROMEOS)
+
+std::string GetNSSErrorMessage() {
+  std::string result;
+  if (PR_GetErrorTextLength()) {
+    std::unique_ptr<char[]> error_text(new char[PR_GetErrorTextLength() + 1]);
+    PRInt32 copied = PR_GetErrorText(error_text.get());
+    result = std::string(error_text.get(), copied);
+  } else {
+    result = base::StringPrintf("NSS error code: %d", PR_GetError());
+  }
+  return result;
+}
+
+#if !defined(OS_CHROMEOS)
+base::FilePath GetDefaultConfigDirectory() {
+  base::FilePath dir;
+  base::PathService::Get(base::DIR_HOME, &dir);
+  if (dir.empty()) {
+    LOG(ERROR) << "Failed to get home directory.";
+    return dir;
+  }
+  dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
+  if (!base::CreateDirectory(dir)) {
+    LOG(ERROR) << "Failed to create " << dir.value() << " directory.";
+    dir.clear();
+  }
+  DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
+  return dir;
+}
+#endif  // !defined(OS_CHROMEOS)
+
+// On non-Chrome OS platforms, return the default config directory. On Chrome OS
+// test images, return a read-only directory with fake root CA certs (which are
+// used by the local Google Accounts server mock we use when testing our login
+// code). On Chrome OS non-test images (where the read-only directory doesn't
+// exist), return an empty path.
+base::FilePath GetInitialConfigDirectory() {
+#if defined(OS_CHROMEOS)
+  base::FilePath database_dir = base::FilePath(kReadOnlyCertDB);
+  if (!base::PathExists(database_dir))
+    database_dir.clear();
+  return database_dir;
+#else
+  return GetDefaultConfigDirectory();
+#endif  // defined(OS_CHROMEOS)
+}
+
+// This callback for NSS forwards all requests to a caller-specified
+// CryptoModuleBlockingPasswordDelegate object.
+char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) {
+  crypto::CryptoModuleBlockingPasswordDelegate* delegate =
+      reinterpret_cast<crypto::CryptoModuleBlockingPasswordDelegate*>(arg);
+  if (delegate) {
+    bool cancelled = false;
+    std::string password = delegate->RequestPassword(PK11_GetTokenName(slot),
+                                                     retry != PR_FALSE,
+                                                     &cancelled);
+    if (cancelled)
+      return nullptr;
+    char* result = PORT_Strdup(password.c_str());
+    password.replace(0, password.size(), password.size(), 0);
+    return result;
+  }
+  DLOG(ERROR) << "PK11 password requested with nullptr arg";
+  return nullptr;
+}
+
+// A singleton to initialize/deinitialize NSPR.
+// Separate from the NSS singleton because we initialize NSPR on the UI thread.
+// Now that we're leaking the singleton, we could merge back with the NSS
+// singleton.
+class NSPRInitSingleton {
+ private:
+  friend struct base::LazyInstanceTraitsBase<NSPRInitSingleton>;
+
+  NSPRInitSingleton() {
+    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+  }
+
+  // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS
+  // to prevent non-joinable threads from using NSS after it's already been
+  // shut down.
+  ~NSPRInitSingleton() = delete;
+};
+
+base::LazyInstance<NSPRInitSingleton>::Leaky
+    g_nspr_singleton = LAZY_INSTANCE_INITIALIZER;
+
+// Force a crash with error info on NSS_NoDB_Init failure.
+void CrashOnNSSInitFailure() {
+  int nss_error = PR_GetError();
+  int os_error = PR_GetOSError();
+  base::debug::Alias(&nss_error);
+  base::debug::Alias(&os_error);
+  LOG(ERROR) << "Error initializing NSS without a persistent database: "
+             << GetNSSErrorMessage();
+  LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error;
+}
+
+#if defined(OS_CHROMEOS)
+class ChromeOSUserData {
+ public:
+  explicit ChromeOSUserData(ScopedPK11Slot public_slot)
+      : public_slot_(std::move(public_slot)),
+        private_slot_initialization_started_(false) {}
+  ~ChromeOSUserData() {
+    if (public_slot_) {
+      SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
+      if (status != SECSuccess)
+        PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+    }
+  }
+
+  ScopedPK11Slot GetPublicSlot() {
+    return ScopedPK11Slot(public_slot_ ? PK11_ReferenceSlot(public_slot_.get())
+                                       : nullptr);
+  }
+
+  ScopedPK11Slot GetPrivateSlot(
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    if (private_slot_)
+      return ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()));
+    if (!callback.is_null())
+      tpm_ready_callback_list_.push_back(std::move(callback));
+    return ScopedPK11Slot();
+  }
+
+  void SetPrivateSlot(ScopedPK11Slot private_slot) {
+    DCHECK(!private_slot_);
+    private_slot_ = std::move(private_slot);
+
+    SlotReadyCallbackList callback_list;
+    callback_list.swap(tpm_ready_callback_list_);
+    for (SlotReadyCallbackList::iterator i = callback_list.begin();
+         i != callback_list.end();
+         ++i) {
+      std::move(*i).Run(
+          ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())));
+    }
+  }
+
+  bool private_slot_initialization_started() const {
+      return private_slot_initialization_started_;
+  }
+
+  void set_private_slot_initialization_started() {
+      private_slot_initialization_started_ = true;
+  }
+
+ private:
+  ScopedPK11Slot public_slot_;
+  ScopedPK11Slot private_slot_;
+
+  bool private_slot_initialization_started_;
+
+  typedef std::vector<base::OnceCallback<void(ScopedPK11Slot)>>
+      SlotReadyCallbackList;
+  SlotReadyCallbackList tpm_ready_callback_list_;
+};
+
+class ScopedChapsLoadFixup {
+ public:
+  ScopedChapsLoadFixup();
+  ~ScopedChapsLoadFixup();
+
+ private:
+#if defined(COMPONENT_BUILD)
+  void* chaps_handle_;
+#endif
+};
+
+#if defined(COMPONENT_BUILD)
+
+ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
+  // HACK: libchaps links the system protobuf and there are symbol conflicts
+  // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
+  chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
+}
+
+ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
+  // LoadModule() will have taken a 2nd reference.
+  if (chaps_handle_)
+    dlclose(chaps_handle_);
+}
+
+#else
+
+ScopedChapsLoadFixup::ScopedChapsLoadFixup() {}
+ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {}
+
+#endif  // defined(COMPONENT_BUILD)
+#endif  // defined(OS_CHROMEOS)
+
+class NSSInitSingleton {
+ public:
+#if defined(OS_CHROMEOS)
+  // Used with PostTaskAndReply to pass handles to worker thread and back.
+  struct TPMModuleAndSlot {
+    explicit TPMModuleAndSlot(SECMODModule* init_chaps_module)
+        : chaps_module(init_chaps_module) {}
+    SECMODModule* chaps_module;
+    crypto::ScopedPK11Slot tpm_slot;
+  };
+
+  ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name,
+                                            const base::FilePath& path) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // NSS is allowed to do IO on the current thread since dispatching
+    // to a dedicated thread would still have the affect of blocking
+    // the current thread, due to NSS's internal locking requirements
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+    base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
+    if (!base::CreateDirectory(nssdb_path)) {
+      LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
+      return ScopedPK11Slot();
+    }
+    return OpenSoftwareNSSDB(nssdb_path, db_name);
+  }
+
+  void EnableTPMTokenForNSS() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    // If this gets set, then we'll use the TPM for certs with
+    // private keys, otherwise we'll fall back to the software
+    // implementation.
+    tpm_token_enabled_for_nss_ = true;
+  }
+
+  bool IsTPMTokenEnabledForNSS() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    return tpm_token_enabled_for_nss_;
+  }
+
+  void InitializeTPMTokenAndSystemSlot(
+      int system_slot_id,
+      base::OnceCallback<void(bool)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // Should not be called while there is already an initialization in
+    // progress.
+    DCHECK(!initializing_tpm_token_);
+    // If EnableTPMTokenForNSS hasn't been called, return false.
+    if (!tpm_token_enabled_for_nss_) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false));
+      return;
+    }
+
+    // If everything is already initialized, then return true.
+    // Note that only |tpm_slot_| is checked, since |chaps_module_| could be
+    // nullptr in tests while |tpm_slot_| has been set to the test DB.
+    if (tpm_slot_) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), true));
+      return;
+    }
+
+    // Note that a reference is not taken to chaps_module_. This is safe since
+    // NSSInitSingleton is Leaky, so the reference it holds is never released.
+    std::unique_ptr<TPMModuleAndSlot> tpm_args(
+        new TPMModuleAndSlot(chaps_module_));
+    TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
+    base::PostTaskWithTraitsAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
+                       system_slot_id, tpm_args_ptr),
+        base::BindOnce(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot,
+                       base::Unretained(this),  // NSSInitSingleton is leaky
+                       std::move(callback), std::move(tpm_args)));
+    initializing_tpm_token_ = true;
+  }
+
+  static void InitializeTPMTokenInThreadPool(CK_SLOT_ID token_slot_id,
+                                             TPMModuleAndSlot* tpm_args) {
+    // NSS functions may reenter //net via extension hooks. If the reentered
+    // code needs to synchronously wait for a task to run but the thread pool in
+    // which that task must run doesn't have enough threads to schedule it, a
+    // deadlock occurs. To prevent that, the base::ScopedBlockingCall below
+    // increments the thread pool capacity for the duration of the TPM
+    // initialization.
+    base::ScopedBlockingCall scoped_blocking_call(
+        base::BlockingType::WILL_BLOCK);
+
+    if (!tpm_args->chaps_module) {
+      ScopedChapsLoadFixup chaps_loader;
+
+      DVLOG(3) << "Loading chaps...";
+      tpm_args->chaps_module = LoadModule(
+          kChapsModuleName,
+          kChapsPath,
+          // For more details on these parameters, see:
+          // https://developer.mozilla.org/en/PKCS11_Module_Specs
+          // slotFlags=[PublicCerts] -- Certificates and public keys can be
+          //   read from this slot without requiring a call to C_Login.
+          // askpw=only -- Only authenticate to the token when necessary.
+          "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
+    }
+    if (tpm_args->chaps_module) {
+      tpm_args->tpm_slot =
+          GetTPMSlotForIdInThreadPool(tpm_args->chaps_module, token_slot_id);
+    }
+  }
+
+  void OnInitializedTPMTokenAndSystemSlot(
+      base::OnceCallback<void(bool)> callback,
+      std::unique_ptr<TPMModuleAndSlot> tpm_args) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module
+             << ", got tpm slot: " << !!tpm_args->tpm_slot;
+
+    chaps_module_ = tpm_args->chaps_module;
+    tpm_slot_ = std::move(tpm_args->tpm_slot);
+    if (!chaps_module_ && test_system_slot_) {
+      // chromeos_unittests try to test the TPM initialization process. If we
+      // have a test DB open, pretend that it is the TPM slot.
+      tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
+    }
+    initializing_tpm_token_ = false;
+
+    if (tpm_slot_)
+      RunAndClearTPMReadyCallbackList();
+
+    std::move(callback).Run(!!tpm_slot_);
+  }
+
+  void RunAndClearTPMReadyCallbackList() {
+    TPMReadyCallbackList callback_list;
+    callback_list.swap(tpm_ready_callback_list_);
+    for (TPMReadyCallbackList::iterator i = callback_list.begin();
+         i != callback_list.end();
+         ++i) {
+      std::move(*i).Run();
+    }
+  }
+
+  bool IsTPMTokenReady(base::OnceClosure callback) {
+    if (!callback.is_null()) {
+      // Cannot DCHECK in the general case yet, but since the callback is
+      // a new addition to the API, DCHECK to make sure at least the new uses
+      // don't regress.
+      DCHECK(thread_checker_.CalledOnValidThread());
+    } else if (!thread_checker_.CalledOnValidThread()) {
+      // TODO(mattm): Change to DCHECK when callers have been fixed.
+      DVLOG(1) << "Called on wrong thread.\n"
+               << base::debug::StackTrace().ToString();
+    }
+
+    if (tpm_slot_)
+      return true;
+
+    if (!callback.is_null())
+      tpm_ready_callback_list_.push_back(std::move(callback));
+
+    return false;
+  }
+
+  // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot
+  // id as an int. This should be safe since this is only used with chaps, which
+  // we also control.
+  static crypto::ScopedPK11Slot GetTPMSlotForIdInThreadPool(
+      SECMODModule* chaps_module,
+      CK_SLOT_ID slot_id) {
+    DCHECK(chaps_module);
+
+    DVLOG(3) << "Poking chaps module.";
+    SECStatus rv = SECMOD_UpdateSlotList(chaps_module);
+    if (rv != SECSuccess)
+      PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
+
+    PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id);
+    if (!slot)
+      LOG(ERROR) << "TPM slot " << slot_id << " not found.";
+    return crypto::ScopedPK11Slot(slot);
+  }
+
+  bool InitializeNSSForChromeOSUser(const std::string& username_hash,
+                                    const base::FilePath& path) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) {
+      // This user already exists in our mapping.
+      DVLOG(2) << username_hash << " already initialized.";
+      return false;
+    }
+
+    DVLOG(2) << "Opening NSS DB " << path.value();
+    std::string db_name = base::StringPrintf(
+        "%s %s", kUserNSSDatabaseName, username_hash.c_str());
+    ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path));
+    chromeos_user_map_[username_hash] =
+        std::make_unique<ChromeOSUserData>(std::move(public_slot));
+    return true;
+  }
+
+  bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    return !chromeos_user_map_[username_hash]
+                ->private_slot_initialization_started();
+  }
+
+  void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    chromeos_user_map_[username_hash]
+        ->set_private_slot_initialization_started();
+  }
+
+  void InitializeTPMForChromeOSUser(const std::string& username_hash,
+                                    CK_SLOT_ID slot_id) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+    DCHECK(chromeos_user_map_[username_hash]->
+               private_slot_initialization_started());
+
+    if (!chaps_module_)
+      return;
+
+    // Note that a reference is not taken to chaps_module_. This is safe since
+    // NSSInitSingleton is Leaky, so the reference it holds is never released.
+    std::unique_ptr<TPMModuleAndSlot> tpm_args(
+        new TPMModuleAndSlot(chaps_module_));
+    TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
+    base::PostTaskWithTraitsAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
+                       slot_id, tpm_args_ptr),
+        base::BindOnce(&NSSInitSingleton::OnInitializedTPMForChromeOSUser,
+                       base::Unretained(this),  // NSSInitSingleton is leaky
+                       username_hash, std::move(tpm_args)));
+  }
+
+  void OnInitializedTPMForChromeOSUser(
+      const std::string& username_hash,
+      std::unique_ptr<TPMModuleAndSlot> tpm_args) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DVLOG(2) << "Got tpm slot for " << username_hash << " "
+             << !!tpm_args->tpm_slot;
+    chromeos_user_map_[username_hash]->SetPrivateSlot(
+        std::move(tpm_args->tpm_slot));
+  }
+
+  void InitializePrivateSoftwareSlotForChromeOSUser(
+      const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    VLOG(1) << "using software private slot for " << username_hash;
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+    DCHECK(chromeos_user_map_[username_hash]->
+               private_slot_initialization_started());
+
+    if (prepared_test_private_slot_) {
+      chromeos_user_map_[username_hash]->SetPrivateSlot(
+          std::move(prepared_test_private_slot_));
+      return;
+    }
+
+    chromeos_user_map_[username_hash]->SetPrivateSlot(
+        chromeos_user_map_[username_hash]->GetPublicSlot());
+  }
+
+  ScopedPK11Slot GetPublicSlotForChromeOSUser(
+      const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    if (username_hash.empty()) {
+      DVLOG(2) << "empty username_hash";
+      return ScopedPK11Slot();
+    }
+
+    if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) {
+      LOG(ERROR) << username_hash << " not initialized.";
+      return ScopedPK11Slot();
+    }
+    return chromeos_user_map_[username_hash]->GetPublicSlot();
+  }
+
+  ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+      const std::string& username_hash,
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    if (username_hash.empty()) {
+      DVLOG(2) << "empty username_hash";
+      if (!callback.is_null()) {
+        base::ThreadTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE, base::BindOnce(std::move(callback), ScopedPK11Slot()));
+      }
+      return ScopedPK11Slot();
+    }
+
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    return chromeos_user_map_[username_hash]->GetPrivateSlot(
+        std::move(callback));
+  }
+
+  void CloseChromeOSUserForTesting(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    auto i = chromeos_user_map_.find(username_hash);
+    DCHECK(i != chromeos_user_map_.end());
+    chromeos_user_map_.erase(i);
+  }
+
+  void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    // Ensure that a previous value of test_system_slot_ is not overwritten.
+    // Unsetting, i.e. setting a nullptr, however is allowed.
+    DCHECK(!slot || !test_system_slot_);
+    test_system_slot_ = std::move(slot);
+    if (test_system_slot_) {
+      tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
+      RunAndClearTPMReadyCallbackList();
+    } else {
+      tpm_slot_.reset();
+    }
+  }
+
+  void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    // Ensure that a previous value of prepared_test_private_slot_ is not
+    // overwritten. Unsetting, i.e. setting a nullptr, however is allowed.
+    DCHECK(!slot || !prepared_test_private_slot_);
+    prepared_test_private_slot_ = std::move(slot);
+  }
+#endif  // defined(OS_CHROMEOS)
+
+#if !defined(OS_CHROMEOS)
+  PK11SlotInfo* GetPersistentNSSKeySlot() {
+    // TODO(mattm): Change to DCHECK when callers have been fixed.
+    if (!thread_checker_.CalledOnValidThread()) {
+      DVLOG(1) << "Called on wrong thread.\n"
+               << base::debug::StackTrace().ToString();
+    }
+
+    return PK11_GetInternalKeySlot();
+  }
+#endif
+
+#if defined(OS_CHROMEOS)
+  void GetSystemNSSKeySlotCallback(
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    std::move(callback).Run(
+        ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())));
+  }
+
+  ScopedPK11Slot GetSystemNSSKeySlot(
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // TODO(mattm): chromeos::TPMTokenloader always calls
+    // InitializeTPMTokenAndSystemSlot with slot 0.  If the system slot is
+    // disabled, tpm_slot_ will be the first user's slot instead. Can that be
+    // detected and return nullptr instead?
+
+    base::OnceClosure wrapped_callback;
+    if (!callback.is_null()) {
+      wrapped_callback = base::BindOnce(
+          &NSSInitSingleton::GetSystemNSSKeySlotCallback,
+          base::Unretained(this) /* singleton is leaky */, std::move(callback));
+    }
+    if (IsTPMTokenReady(std::move(wrapped_callback)))
+      return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()));
+    return ScopedPK11Slot();
+  }
+#endif
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<NSSInitSingleton>;
+
+  NSSInitSingleton()
+      : tpm_token_enabled_for_nss_(false),
+        initializing_tpm_token_(false),
+        chaps_module_(nullptr),
+        root_(nullptr) {
+    // Initializing NSS causes us to do blocking IO.
+    // Temporarily allow it until we fix
+    //   http://code.google.com/p/chromium/issues/detail?id=59847
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+    // It's safe to construct on any thread, since LazyInstance will prevent any
+    // other threads from accessing until the constructor is done.
+    thread_checker_.DetachFromThread();
+
+    EnsureNSPRInit();
+
+    // We *must* have NSS >= 3.26 at compile time.
+    static_assert((NSS_VMAJOR == 3 && NSS_VMINOR >= 26) || (NSS_VMAJOR > 3),
+                  "nss version check failed");
+    // Also check the run-time NSS version.
+    // NSS_VersionCheck is a >= check, not strict equality.
+    if (!NSS_VersionCheck("3.26")) {
+      LOG(FATAL) << "NSS_VersionCheck(\"3.26\") failed. NSS >= 3.26 is "
+                    "required. Please upgrade to the latest NSS, and if you "
+                    "still get this error, contact your distribution "
+                    "maintainer.";
+    }
+
+    SECStatus status = SECFailure;
+    base::FilePath database_dir = GetInitialConfigDirectory();
+    if (!database_dir.empty()) {
+      // Initialize with a persistent database (likely, ~/.pki/nssdb).
+      // Use "sql:" which can be shared by multiple processes safely.
+      std::string nss_config_dir =
+          base::StringPrintf("sql:%s", database_dir.value().c_str());
+#if defined(OS_CHROMEOS)
+      status = NSS_Init(nss_config_dir.c_str());
+#else
+      status = NSS_InitReadWrite(nss_config_dir.c_str());
+#endif
+      if (status != SECSuccess) {
+        LOG(ERROR) << "Error initializing NSS with a persistent "
+                      "database (" << nss_config_dir
+                   << "): " << GetNSSErrorMessage();
+      }
+    }
+    if (status != SECSuccess) {
+      VLOG(1) << "Initializing NSS without a persistent database.";
+      status = NSS_NoDB_Init(nullptr);
+      if (status != SECSuccess) {
+        CrashOnNSSInitFailure();
+        return;
+      }
+    }
+
+    PK11_SetPasswordFunc(PKCS11PasswordFunc);
+
+    // If we haven't initialized the password for the NSS databases,
+    // initialize an empty-string password so that we don't need to
+    // log in.
+    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
+    if (slot) {
+      // PK11_InitPin may write to the keyDB, but no other thread can use NSS
+      // yet, so we don't need to lock.
+      if (PK11_NeedUserInit(slot))
+        PK11_InitPin(slot, nullptr, nullptr);
+      PK11_FreeSlot(slot);
+    }
+
+    root_ = InitDefaultRootCerts();
+
+    // Disable MD5 certificate signatures. (They are disabled by default in
+    // NSS 3.14.)
+    NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE);
+    NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
+                           0, NSS_USE_ALG_IN_CERT_SIGNATURE);
+  }
+
+  // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS
+  // to prevent non-joinable threads from using NSS after it's already been
+  // shut down.
+  ~NSSInitSingleton() = delete;
+
+  // Load nss's built-in root certs.
+  SECMODModule* InitDefaultRootCerts() {
+    SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", nullptr);
+    if (root)
+      return root;
+
+    // Aw, snap.  Can't find/load root cert shared library.
+    // This will make it hard to talk to anybody via https.
+    // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed.
+    return nullptr;
+  }
+
+  // Load the given module for this NSS session.
+  static SECMODModule* LoadModule(const char* name,
+                                  const char* library_path,
+                                  const char* params) {
+    std::string modparams = base::StringPrintf(
+        "name=\"%s\" library=\"%s\" %s",
+        name, library_path, params ? params : "");
+
+    // Shouldn't need to const_cast here, but SECMOD doesn't properly
+    // declare input string arguments as const.  Bug
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed
+    // on NSS codebase to address this.
+    SECMODModule* module = SECMOD_LoadUserModule(
+        const_cast<char*>(modparams.c_str()), nullptr, PR_FALSE);
+    if (!module) {
+      LOG(ERROR) << "Error loading " << name << " module into NSS: "
+                 << GetNSSErrorMessage();
+      return nullptr;
+    }
+    if (!module->loaded) {
+      LOG(ERROR) << "After loading " << name << ", loaded==false: "
+                 << GetNSSErrorMessage();
+      SECMOD_DestroyModule(module);
+      return nullptr;
+    }
+    return module;
+  }
+
+  bool tpm_token_enabled_for_nss_;
+  bool initializing_tpm_token_;
+  typedef std::vector<base::OnceClosure> TPMReadyCallbackList;
+  TPMReadyCallbackList tpm_ready_callback_list_;
+  SECMODModule* chaps_module_;
+  crypto::ScopedPK11Slot tpm_slot_;
+  SECMODModule* root_;
+#if defined(OS_CHROMEOS)
+  std::map<std::string, std::unique_ptr<ChromeOSUserData>> chromeos_user_map_;
+  ScopedPK11Slot test_system_slot_;
+  ScopedPK11Slot prepared_test_private_slot_;
+#endif
+
+  base::ThreadChecker thread_checker_;
+};
+
+base::LazyInstance<NSSInitSingleton>::Leaky
+    g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
+}  // namespace
+
+ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
+                                 const std::string& description) {
+  const std::string modspec =
+      base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
+                         path.value().c_str(),
+                         description.c_str());
+  PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
+  if (db_slot) {
+    if (PK11_NeedUserInit(db_slot))
+      PK11_InitPin(db_slot, nullptr, nullptr);
+  } else {
+    LOG(ERROR) << "Error opening persistent database (" << modspec
+               << "): " << GetNSSErrorMessage();
+  }
+  return ScopedPK11Slot(db_slot);
+}
+
+void EnsureNSPRInit() {
+  g_nspr_singleton.Get();
+}
+
+void EnsureNSSInit() {
+  g_nss_singleton.Get();
+}
+
+bool CheckNSSVersion(const char* version) {
+  return !!NSS_VersionCheck(version);
+}
+
+AutoSECMODListReadLock::AutoSECMODListReadLock()
+      : lock_(SECMOD_GetDefaultModuleListLock()) {
+    SECMOD_GetReadLock(lock_);
+  }
+
+AutoSECMODListReadLock::~AutoSECMODListReadLock() {
+  SECMOD_ReleaseReadLock(lock_);
+}
+
+#if defined(OS_CHROMEOS)
+ScopedPK11Slot GetSystemNSSKeySlot(
+    base::OnceCallback<void(ScopedPK11Slot)> callback) {
+  return g_nss_singleton.Get().GetSystemNSSKeySlot(std::move(callback));
+}
+
+void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+  g_nss_singleton.Get().SetSystemKeySlotForTesting(std::move(slot));
+}
+
+void EnableTPMTokenForNSS() {
+  g_nss_singleton.Get().EnableTPMTokenForNSS();
+}
+
+bool IsTPMTokenEnabledForNSS() {
+  return g_nss_singleton.Get().IsTPMTokenEnabledForNSS();
+}
+
+bool IsTPMTokenReady(base::OnceClosure callback) {
+  return g_nss_singleton.Get().IsTPMTokenReady(std::move(callback));
+}
+
+void InitializeTPMTokenAndSystemSlot(int token_slot_id,
+                                     base::OnceCallback<void(bool)> callback) {
+  g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id,
+                                                        std::move(callback));
+}
+
+bool InitializeNSSForChromeOSUser(const std::string& username_hash,
+                                  const base::FilePath& path) {
+  return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash,
+                                                            path);
+}
+
+bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+  return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser(
+      username_hash);
+}
+
+void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+  g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash);
+}
+
+void InitializeTPMForChromeOSUser(
+    const std::string& username_hash,
+    CK_SLOT_ID slot_id) {
+  g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id);
+}
+
+void InitializePrivateSoftwareSlotForChromeOSUser(
+    const std::string& username_hash) {
+  g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser(
+      username_hash);
+}
+
+ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) {
+  return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash);
+}
+
+ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+    const std::string& username_hash,
+    base::OnceCallback<void(ScopedPK11Slot)> callback) {
+  return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(
+      username_hash, std::move(callback));
+}
+
+void CloseChromeOSUserForTesting(const std::string& username_hash) {
+  g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash);
+}
+
+void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) {
+  g_nss_singleton.Get().SetPrivateSoftwareSlotForChromeOSUserForTesting(
+      std::move(slot));
+}
+#endif  // defined(OS_CHROMEOS)
+
+base::Time PRTimeToBaseTime(PRTime prtime) {
+  return base::Time::FromInternalValue(
+      prtime + base::Time::UnixEpoch().ToInternalValue());
+}
+
+PRTime BaseTimeToPRTime(base::Time time) {
+  return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
+}
+
+#if !defined(OS_CHROMEOS)
+PK11SlotInfo* GetPersistentNSSKeySlot() {
+  return g_nss_singleton.Get().GetPersistentNSSKeySlot();
+}
+#endif
+
+}  // namespace crypto
diff --git a/src/crypto/nss_util.h b/src/crypto/nss_util.h
index 7b50781..aa918a6 100644
--- a/src/crypto/nss_util.h
+++ b/src/crypto/nss_util.h
@@ -6,15 +6,13 @@
 #define CRYPTO_NSS_UTIL_H_
 
 #include <string>
-#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "crypto/crypto_export.h"
-
-#if defined(USE_NSS)
-class FilePath;
-#endif  // defined(USE_NSS)
+#include "starboard/types.h"
 
 namespace base {
-class Lock;
 class Time;
 }  // namespace base
 
@@ -23,160 +21,55 @@
 // initialization functions.
 namespace crypto {
 
-class SymmetricKey;
-
-#if defined(USE_NSS)
-// EarlySetupForNSSInit performs lightweight setup which must occur before the
-// process goes multithreaded. This does not initialise NSS. For test, see
-// EnsureNSSInit.
-CRYPTO_EXPORT void EarlySetupForNSSInit();
-#endif
-
 // Initialize NRPR if it isn't already initialized.  This function is
 // thread-safe, and NSPR will only ever be initialized once.
 CRYPTO_EXPORT void EnsureNSPRInit();
 
-// Initialize NSS safely for strict sandboxing.  This function tells NSS to not
-// load user security modules, and makes sure NSS will have proper entropy in a
-// restricted, sandboxed environment.
-//
-// As a defense in depth measure, this function should be called in a sandboxed
-// environment.  That way, in the event of a bug, NSS will still not be able to
-// load security modules that could expose private data and keys.
-//
-// Make sure to get an LGTM from the Chrome Security Team if you use this.
-CRYPTO_EXPORT void InitNSSSafely();
-
 // Initialize NSS if it isn't already initialized.  This must be called before
 // any other NSS functions.  This function is thread-safe, and NSS will only
 // ever be initialized once.
 CRYPTO_EXPORT void EnsureNSSInit();
 
-// Call this before calling EnsureNSSInit() will force NSS to initialize
-// without a persistent DB.  This is used for the special case where access of
-// persistent DB is prohibited.
-//
-// TODO(hclam): Isolate loading default root certs.
-//
-// NSS will be initialized without loading any user security modules, including
-// the built-in root certificates module. User security modules need to be
-// loaded manually after NSS initialization.
-//
-// If EnsureNSSInit() is called before then this function has no effect.
-//
-// Calling this method only has effect on Linux.
-//
-// WARNING: Use this with caution.
-CRYPTO_EXPORT void ForceNSSNoDBInit();
-
-// This method is used to disable checks in NSS when used in a forked process.
-// NSS checks whether it is running a forked process to avoid problems when
-// using user security modules in a forked process.  However if we are sure
-// there are no modules loaded before the process is forked then there is no
-// harm disabling the check.
-//
-// This method must be called before EnsureNSSInit() to take effect.
-//
-// WARNING: Use this with caution.
-CRYPTO_EXPORT void DisableNSSForkCheck();
-
-// Load NSS library files. This function has no effect on Mac and Windows.
-// This loads the necessary NSS library files so that NSS can be initialized
-// after loading additional library files is disallowed, for example when the
-// sandbox is active.
-//
-// Note that this does not load libnssckbi.so which contains the root
-// certificates.
-CRYPTO_EXPORT void LoadNSSLibraries();
-
 // Check if the current NSS version is greater than or equals to |version|.
 // A sample version string is "3.12.3".
 bool CheckNSSVersion(const char* version);
 
 #if defined(OS_CHROMEOS)
-// Open the r/w nssdb that's stored inside the user's encrypted home
-// directory.  This is the default slot returned by
-// GetPublicNSSKeySlot().
-CRYPTO_EXPORT void OpenPersistentNSSDB();
-
-// Indicates that NSS should load the Chaps library so that we
-// can access the TPM through NSS.  Once this is called,
-// GetPrivateNSSKeySlot() will return the TPM slot if one was found.
+// Indicates that NSS should use the Chaps library so that we
+// can access the TPM through NSS.  InitializeTPMTokenAndSystemSlot and
+// InitializeTPMForChromeOSUser must still be called to load the slots.
 CRYPTO_EXPORT void EnableTPMTokenForNSS();
 
-// Get name and user PIN for the built-in TPM token on ChromeOS.
-// Either one can safely be NULL.  Should only be called after
-// EnableTPMTokenForNSS has been called with a non-null delegate.
-CRYPTO_EXPORT void GetTPMTokenInfo(std::string* token_name,
-                                   std::string* user_pin);
+// Returns true if EnableTPMTokenForNSS has been called.
+CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS();
 
 // Returns true if the TPM is owned and PKCS#11 initialized with the
 // user and security officer PINs, and has been enabled in NSS by
 // calling EnableTPMForNSS, and Chaps has been successfully
 // loaded into NSS.
-CRYPTO_EXPORT bool IsTPMTokenReady();
+// If |callback| is non-null and the function returns false, the |callback| will
+// be run once the TPM is ready. |callback| will never be run if the function
+// returns true.
+CRYPTO_EXPORT bool IsTPMTokenReady(base::OnceClosure callback)
+    WARN_UNUSED_RESULT;
 
-// Initialize the TPM token.  Does nothing if it is already initialized.
-CRYPTO_EXPORT bool InitializeTPMToken(const std::string& token_name,
-                                      const std::string& user_pin);
-
-// Gets supplemental user key. Creates one in NSS database if it does not exist.
-// The supplemental user key is used for AES encryption of user data that is
-// stored and protected by cryptohome. This additional layer of encryption of
-// provided to ensure that sensitive data wouldn't be exposed in plain text in
-// case when an attacker would somehow gain access to all content within
-// cryptohome.
-CRYPTO_EXPORT SymmetricKey* GetSupplementalUserKey();
+// Initialize the TPM token and system slot. The |callback| will run on the same
+// thread with true if the token and slot were successfully loaded or were
+// already initialized. |callback| will be passed false if loading failed.  Once
+// called, InitializeTPMTokenAndSystemSlot must not be called again until the
+// |callback| has been run.
+CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot(
+    int system_slot_id,
+    base::OnceCallback<void(bool)> callback);
 #endif
 
 // Convert a NSS PRTime value into a base::Time object.
-// We use a int64 instead of PRTime here to avoid depending on NSPR headers.
-CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64 prtime);
+// We use a int64_t instead of PRTime here to avoid depending on NSPR headers.
+CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64_t prtime);
 
 // Convert a base::Time object into a PRTime value.
-// We use a int64 instead of PRTime here to avoid depending on NSPR headers.
-CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time);
-
-#if defined(USE_NSS)
-// Exposed for unittests only.
-// TODO(mattm): When NSS 3.14 is the minimum version required,
-// switch back to using a separate user DB for each test.
-// Because of https://bugzilla.mozilla.org/show_bug.cgi?id=588269 , the
-// opened user DB is not automatically closed.
-class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB {
- public:
-  ScopedTestNSSDB();
-  ~ScopedTestNSSDB();
-
-  bool is_open() { return is_open_; }
-
- private:
-  bool is_open_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB);
-};
-
-// NSS has a bug which can cause a deadlock or stall in some cases when writing
-// to the certDB and keyDB. It also has a bug which causes concurrent key pair
-// generations to scribble over each other. To work around this, we synchronize
-// writes to the NSS databases with a global lock. The lock is hidden beneath a
-// function for easy disabling when the bug is fixed. Callers should allow for
-// it to return NULL in the future.
-//
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=564011
-base::Lock* GetNSSWriteLock();
-
-// A helper class that acquires the NSS write Lock while the AutoNSSWriteLock
-// is in scope.
-class CRYPTO_EXPORT AutoNSSWriteLock {
- public:
-  AutoNSSWriteLock();
-  ~AutoNSSWriteLock();
- private:
-  base::Lock *lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock);
-};
-
-#endif  // defined(USE_NSS)
+// We use a int64_t instead of PRTime here to avoid depending on NSPR headers.
+CRYPTO_EXPORT int64_t BaseTimeToPRTime(base::Time time);
 
 }  // namespace crypto
 
diff --git a/src/crypto/nss_util_internal.h b/src/crypto/nss_util_internal.h
new file mode 100644
index 0000000..fdc0035
--- /dev/null
+++ b/src/crypto/nss_util_internal.h
@@ -0,0 +1,127 @@
+// Copyright (c) 2012 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_NSS_UTIL_INTERNAL_H_
+#define CRYPTO_NSS_UTIL_INTERNAL_H_
+
+#include <secmodt.h>
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+#include "starboard/types.h"
+
+namespace base {
+class FilePath;
+}
+
+// These functions return a type defined in an NSS header, and so cannot be
+// declared in nss_util.h.  Hence, they are declared here.
+
+namespace crypto {
+
+// Opens an NSS software database in folder |path|, with the (potentially)
+// user-visible description |description|. Returns the slot for the opened
+// database, or nullptr if the database could not be opened.
+CRYPTO_EXPORT ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
+                                               const std::string& description);
+
+#if !defined(OS_CHROMEOS)
+// Returns a reference to the default NSS key slot for storing persistent data.
+// Caller must release returned reference with PK11_FreeSlot.
+CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot() WARN_UNUSED_RESULT;
+#endif
+
+// A helper class that acquires the SECMOD list read lock while the
+// AutoSECMODListReadLock is in scope.
+class CRYPTO_EXPORT AutoSECMODListReadLock {
+ public:
+  AutoSECMODListReadLock();
+  ~AutoSECMODListReadLock();
+
+ private:
+  SECMODListLock* lock_;
+  DISALLOW_COPY_AND_ASSIGN(AutoSECMODListReadLock);
+};
+
+#if defined(OS_CHROMEOS)
+// Returns a reference to the system-wide TPM slot if it is loaded. If it is not
+// loaded and |callback| is non-null, the |callback| will be run once the slot
+// is loaded.
+CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot(
+    base::OnceCallback<void(ScopedPK11Slot)> callback) WARN_UNUSED_RESULT;
+
+// Sets the test system slot to |slot|, which means that |slot| will be exposed
+// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if the test system slot is set.
+// This must must not be called consecutively with a |slot| != nullptr. If
+// |slot| is nullptr, the test system slot is unset.
+CRYPTO_EXPORT void SetSystemKeySlotForTesting(ScopedPK11Slot slot);
+
+// Prepare per-user NSS slot mapping. It is safe to call this function multiple
+// times. Returns true if the user was added, or false if it already existed.
+CRYPTO_EXPORT bool InitializeNSSForChromeOSUser(
+    const std::string& username_hash,
+    const base::FilePath& path);
+
+// Returns whether TPM for ChromeOS user still needs initialization. If
+// true is returned, the caller can proceed to initialize TPM slot for the
+// user, but should call |WillInitializeTPMForChromeOSUser| first.
+// |InitializeNSSForChromeOSUser| must have been called first.
+CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser(
+    const std::string& username_hash) WARN_UNUSED_RESULT;
+
+// Makes |ShouldInitializeTPMForChromeOSUser| start returning false.
+// Should be called before starting TPM initialization for the user.
+// Assumes |InitializeNSSForChromeOSUser| had already been called.
+CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser(
+    const std::string& username_hash);
+
+// Use TPM slot |slot_id| for user.  InitializeNSSForChromeOSUser must have been
+// called first.
+CRYPTO_EXPORT void InitializeTPMForChromeOSUser(
+    const std::string& username_hash,
+    CK_SLOT_ID slot_id);
+
+// Use the software slot as the private slot for user.
+// InitializeNSSForChromeOSUser must have been called first.
+CRYPTO_EXPORT void InitializePrivateSoftwareSlotForChromeOSUser(
+    const std::string& username_hash);
+
+// Returns a reference to the public slot for user.
+CRYPTO_EXPORT ScopedPK11Slot GetPublicSlotForChromeOSUser(
+    const std::string& username_hash) WARN_UNUSED_RESULT;
+
+// Returns the private slot for |username_hash| if it is loaded. If it is not
+// loaded and |callback| is non-null, the |callback| will be run once the slot
+// is loaded.
+CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+    const std::string& username_hash,
+    base::OnceCallback<void(ScopedPK11Slot)> callback) WARN_UNUSED_RESULT;
+
+// Closes the NSS DB for |username_hash| that was previously opened by the
+// *Initialize*ForChromeOSUser functions.
+CRYPTO_EXPORT void CloseChromeOSUserForTesting(
+    const std::string& username_hash);
+
+// Sets the slot which should be used as private slot for the next
+// |InitializePrivateSoftwareSlotForChromeOSUser| called. This is intended for
+// simulating a separate private slot in Chrome OS browser tests.
+// As a sanity check, it is recommended to check that the private slot of the
+// profile's certificate database is set to |slot| when the profile is
+// available, because |slot| will be used as private slot for whichever profile
+// is initialized next.
+CRYPTO_EXPORT void SetPrivateSoftwareSlotForChromeOSUserForTesting(
+    ScopedPK11Slot slot);
+
+#endif  // defined(OS_CHROMEOS)
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_UTIL_INTERNAL_H_
diff --git a/src/crypto/nss_util_unittest.cc b/src/crypto/nss_util_unittest.cc
new file mode 100644
index 0000000..1f4efb3
--- /dev/null
+++ b/src/crypto/nss_util_unittest.cc
@@ -0,0 +1,45 @@
+// 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 "crypto/nss_util.h"
+
+#include <prtime.h>
+
+#include "base/time/time.h"
+#include "starboard/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+TEST(NSSUtilTest, PRTimeConversion) {
+  EXPECT_EQ(base::Time::UnixEpoch(), PRTimeToBaseTime(0));
+  EXPECT_EQ(0, BaseTimeToPRTime(base::Time::UnixEpoch()));
+
+  PRExplodedTime prxtime;
+  prxtime.tm_params.tp_gmt_offset = 0;
+  prxtime.tm_params.tp_dst_offset = 0;
+  base::Time::Exploded exploded;
+  exploded.year = prxtime.tm_year = 2011;
+  exploded.month = 12;
+  prxtime.tm_month = 11;
+  // PRExplodedTime::tm_wday is a smaller type than Exploded::day_of_week, so
+  // assigning the two in this order instead of the reverse avoids potential
+  // warnings about type downcasting.
+  exploded.day_of_week = prxtime.tm_wday = 0;  // Should be unused.
+  exploded.day_of_month = prxtime.tm_mday = 10;
+  exploded.hour = prxtime.tm_hour = 2;
+  exploded.minute = prxtime.tm_min = 52;
+  exploded.second = prxtime.tm_sec = 19;
+  exploded.millisecond = 342;
+  prxtime.tm_usec = 342000;
+
+  PRTime pr_time = PR_ImplodeTime(&prxtime);
+  base::Time base_time;
+  EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &base_time));
+
+  EXPECT_EQ(base_time, PRTimeToBaseTime(pr_time));
+  EXPECT_EQ(pr_time, BaseTimeToPRTime(base_time));
+}
+
+}  // namespace crypto
diff --git a/src/crypto/openssl_util.cc b/src/crypto/openssl_util.cc
index bdf24e6..295da2f 100644
--- a/src/crypto/openssl_util.cc
+++ b/src/crypto/openssl_util.cc
@@ -4,77 +4,18 @@
 
 #include "crypto/openssl_util.h"
 
-#include <openssl/err.h>
-#include <openssl/ssl.h>
+#include <string>
 
 #include "base/logging.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/singleton.h"
-#include "base/string_piece.h"
-#include "base/synchronization/lock.h"
+#include "base/strings/string_piece.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/crypto.h"
+#include "third_party/boringssl/src/include/openssl/err.h"
 
 namespace crypto {
 
 namespace {
 
-unsigned long CurrentThreadId() {
-  return static_cast<unsigned long>(base::PlatformThread::CurrentId());
-}
-
-// Singleton for initializing and cleaning up the OpenSSL library.
-class OpenSSLInitSingleton {
- public:
-  static OpenSSLInitSingleton* GetInstance() {
-    // We allow the SSL environment to leak for multiple reasons:
-    //   -  it is used from a non-joinable worker thread that is not stopped on
-    //      shutdown, hence may still be using OpenSSL library after the AtExit
-    //      runner has completed.
-    //   -  There are other OpenSSL related singletons (e.g. the client socket
-    //      context) who's cleanup depends on the global environment here, but
-    //      we can't control the order the AtExit handlers will run in so
-    //      allowing the global environment to leak at least ensures it is
-    //      available for those other singletons to reliably cleanup.
-    return Singleton<OpenSSLInitSingleton,
-               LeakySingletonTraits<OpenSSLInitSingleton> >::get();
-  }
- private:
-  friend struct DefaultSingletonTraits<OpenSSLInitSingleton>;
-  OpenSSLInitSingleton() {
-    SSL_load_error_strings();
-    SSL_library_init();
-    OpenSSL_add_all_algorithms();
-    int num_locks = CRYPTO_num_locks();
-    locks_.reserve(num_locks);
-    for (int i = 0; i < num_locks; ++i)
-      locks_.push_back(new base::Lock());
-    CRYPTO_set_locking_callback(LockingCallback);
-    CRYPTO_set_id_callback(CurrentThreadId);
-  }
-
-  ~OpenSSLInitSingleton() {
-    CRYPTO_set_locking_callback(NULL);
-    EVP_cleanup();
-    ERR_free_strings();
-  }
-
-  static void LockingCallback(int mode, int n, const char* file, int line) {
-    OpenSSLInitSingleton::GetInstance()->OnLockingCallback(mode, n, file, line);
-  }
-
-  void OnLockingCallback(int mode, int n, const char* file, int line) {
-    CHECK_LT(static_cast<size_t>(n), locks_.size());
-    if (mode & CRYPTO_LOCK)
-      locks_[n]->Acquire();
-    else
-      locks_[n]->Release();
-  }
-
-  // These locks are used and managed by OpenSSL via LockingCallback().
-  ScopedVector<base::Lock> locks_;
-
-  DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton);
-};
-
 // Callback routine for OpenSSL to print error messages. |str| is a
 // NULL-terminated string of length |len| containing diagnostic information
 // such as the library, function and reason for the error, the file and line
@@ -92,18 +33,17 @@
 }  // namespace
 
 void EnsureOpenSSLInit() {
-  (void)OpenSSLInitSingleton::GetInstance();
+  // CRYPTO_library_init may be safely called concurrently.
+  CRYPTO_library_init();
 }
 
-void ClearOpenSSLERRStack(const tracked_objects::Location& location) {
-  if (logging::DEBUG_MODE && VLOG_IS_ON(1)) {
-    int error_num = ERR_peek_error();
+void ClearOpenSSLERRStack(const base::Location& location) {
+  if (DCHECK_IS_ON() && VLOG_IS_ON(1)) {
+    uint32_t error_num = ERR_peek_error();
     if (error_num == 0)
       return;
 
-    std::string message;
-    location.Write(true, true, &message);
-    DVLOG(1) << "OpenSSL ERR_get_error stack from " << message;
+    DVLOG(1) << "OpenSSL ERR_get_error stack from " << location.ToString();
     ERR_print_errors_cb(&OpenSSLErrorCallback, NULL);
   } else {
     ERR_clear_error();
diff --git a/src/crypto/openssl_util.h b/src/crypto/openssl_util.h
index b390fe7..b546503 100644
--- a/src/crypto/openssl_util.h
+++ b/src/crypto/openssl_util.h
@@ -5,40 +5,17 @@
 #ifndef CRYPTO_OPENSSL_UTIL_H_
 #define CRYPTO_OPENSSL_UTIL_H_
 
-#include "base/basictypes.h"
 #include "base/location.h"
+#include "base/macros.h"
 #include "crypto/crypto_export.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
-// A helper class that takes care of destroying OpenSSL objects when it goes out
-// of scope.
-template <typename T, void (*destructor)(T*)>
-class ScopedOpenSSL {
- public:
-  ScopedOpenSSL() : ptr_(NULL) { }
-  explicit ScopedOpenSSL(T* ptr) : ptr_(ptr) { }
-  ~ScopedOpenSSL() {
-    reset(NULL);
-  }
-
-  T* get() const { return ptr_; }
-  void reset(T* ptr) {
-    if (ptr != ptr_) {
-      if (ptr_) (*destructor)(ptr_);
-      ptr_ = ptr;
-    }
-  }
-
- private:
-  T* ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSL);
-};
-
 // Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's
 // SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those
-// of the our base wrapper APIs.
+// of our base wrapper APIs.
 // This allows the library to write directly to the caller's buffer if it is of
 // sufficient size, but if not it will write to temporary |min_sized_buffer_|
 // of required size and then its content is automatically copied out on
@@ -54,7 +31,7 @@
   ~ScopedOpenSSLSafeSizeBuffer() {
     if (output_len_ < MIN_SIZE) {
       // Copy the temporary buffer out, truncating as needed.
-      memcpy(output_, min_sized_buffer_, output_len_);
+      SbMemoryCopy(output_, min_sized_buffer_, output_len_);
     }
     // else... any writing already happened directly into |output_|.
   }
@@ -77,16 +54,16 @@
 };
 
 // Initialize OpenSSL if it isn't already initialized. This must be called
-// before any other OpenSSL functions.
+// before any other OpenSSL functions though it is safe and cheap to call this
+// multiple times.
 // This function is thread-safe, and OpenSSL will only ever be initialized once.
 // OpenSSL will be properly shut down on program exit.
-void CRYPTO_EXPORT EnsureOpenSSLInit();
+CRYPTO_EXPORT void EnsureOpenSSLInit();
 
 // Drains the OpenSSL ERR_get_error stack. On a debug build the error codes
 // are send to VLOG(1), on a release build they are disregarded. In most
 // cases you should pass FROM_HERE as the |location|.
-void CRYPTO_EXPORT ClearOpenSSLERRStack(
-    const tracked_objects::Location& location);
+CRYPTO_EXPORT void ClearOpenSSLERRStack(const base::Location& location);
 
 // Place an instance of this class on the call stack to automatically clear
 // the OpenSSL error stack on function exit.
@@ -95,7 +72,7 @@
   // Pass FROM_HERE as |location|, to help track the source of OpenSSL error
   // messages. Note any diagnostic emitted will be tagged with the location of
   // the constructor call as it's not possible to trace a destructor's callsite.
-  explicit OpenSSLErrStackTracer(const tracked_objects::Location& location)
+  explicit OpenSSLErrStackTracer(const base::Location& location)
       : location_(location) {
     EnsureOpenSSLInit();
   }
@@ -104,7 +81,7 @@
   }
 
  private:
-  const tracked_objects::Location location_;
+  const base::Location location_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(OpenSSLErrStackTracer);
 };
diff --git a/src/crypto/p224.cc b/src/crypto/p224.cc
index f9ee385..52e59ce 100644
--- a/src/crypto/p224.cc
+++ b/src/crypto/p224.cc
@@ -12,6 +12,8 @@
 #include <string.h>
 
 #include "base/sys_byteorder.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 
 namespace {
 
@@ -20,11 +22,11 @@
 
 // Field element functions.
 //
-// The field that we're dealing with is Z/pZ where p = 2**224 - 2**96 + 1.
+// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
 //
 // Field elements are represented by a FieldElement, which is a typedef to an
-// array of 8 uint32's. The value of a FieldElement, a, is:
-//   a[0] + 2**28*a[1] + 2**56*a[2] + ... + 2**196*a[7]
+// array of 8 uint32_t's. The value of a FieldElement, a, is:
+//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
 //
 // Using 28-bit limbs means that there's only 4 bits of headroom, which is less
 // than we would really like. But it has the useful feature that we hit 2**224
@@ -41,12 +43,12 @@
 void Contract(FieldElement* inout);
 
 // IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise.
-uint32 IsZero(const FieldElement& a) {
+uint32_t IsZero(const FieldElement& a) {
   FieldElement minimal;
-  memcpy(&minimal, &a, sizeof(minimal));
+  SbMemoryCopy(&minimal, &a, sizeof(minimal));
   Contract(&minimal);
 
-  uint32 is_zero = 0, is_p = 0;
+  uint32_t is_zero = 0, is_p = 0;
   for (unsigned i = 0; i < 8; i++) {
     is_zero |= minimal[i];
     is_p |= minimal[i] - kP[i];
@@ -68,7 +70,7 @@
   // For is_zero and is_p, the LSB is 0 iff all the bits are zero.
   is_zero &= is_p & 1;
   is_zero = (~is_zero) << 31;
-  is_zero = static_cast<int32>(is_zero) >> 31;
+  is_zero = static_cast<int32_t>(is_zero) >> 31;
   return is_zero;
 }
 
@@ -81,9 +83,9 @@
   }
 }
 
-static const uint32 kTwo31p3 = (1u<<31) + (1u<<3);
-static const uint32 kTwo31m3 = (1u<<31) - (1u<<3);
-static const uint32 kTwo31m15m3 = (1u<<31) - (1u<<15) - (1u<<3);
+static const uint32_t kTwo31p3 = (1u << 31) + (1u << 3);
+static const uint32_t kTwo31m3 = (1u << 31) - (1u << 3);
+static const uint32_t kTwo31m15m3 = (1u << 31) - (1u << 15) - (1u << 3);
 // kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can
 // subtract smaller amounts without underflow. See the section "Subtraction" in
 // [1] for why.
@@ -103,22 +105,22 @@
   }
 }
 
-static const uint64 kTwo63p35 = (1ull<<63) + (1ull<<35);
-static const uint64 kTwo63m35 = (1ull<<63) - (1ull<<35);
-static const uint64 kTwo63m35m19 = (1ull<<63) - (1ull<<35) - (1ull<<19);
+static const uint64_t kTwo63p35 = (1ull << 63) + (1ull << 35);
+static const uint64_t kTwo63m35 = (1ull << 63) - (1ull << 35);
+static const uint64_t kTwo63m35m19 = (1ull << 63) - (1ull << 35) - (1ull << 19);
 // kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section
 // "Subtraction" in [1] for why.
-static const uint64 kZero63ModP[8] = {
-  kTwo63p35, kTwo63m35, kTwo63m35, kTwo63m35,
-  kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35,
+static const uint64_t kZero63ModP[8] = {
+    kTwo63p35,    kTwo63m35, kTwo63m35, kTwo63m35,
+    kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35,
 };
 
-static const uint32 kBottom28Bits = 0xfffffff;
+static const uint32_t kBottom28Bits = 0xfffffff;
 
 // LargeFieldElement also represents an element of the field. The limbs are
 // still spaced 28-bits apart and in little-endian order. So the limbs are at
 // 0, 28, 56, ..., 392 bits, each 64-bits wide.
-typedef uint64 LargeFieldElement[15];
+typedef uint64_t LargeFieldElement[15];
 
 // ReduceLarge converts a LargeFieldElement to a FieldElement.
 //
@@ -144,21 +146,21 @@
   // 32-bit operations.
   for (int i = 1; i < 8; i++) {
     in[i+1] += in[i] >> 28;
-    (*out)[i] = static_cast<uint32>(in[i] & kBottom28Bits);
+    (*out)[i] = static_cast<uint32_t>(in[i] & kBottom28Bits);
   }
   // Eliminate the term at 2*224 that we introduced while keeping the same
   // value mod p.
   in[0] -= in[8];  // reflection off the "+1" term of p.
-  (*out)[3] += static_cast<uint32>(in[8] & 0xffff) << 12; // "-2**96" term
-  (*out)[4] += static_cast<uint32>(in[8] >> 16);  // rest of "-2**96" term
+  (*out)[3] += static_cast<uint32_t>(in[8] & 0xffff) << 12;  // "-2**96" term
+  (*out)[4] += static_cast<uint32_t>(in[8] >> 16);  // rest of "-2**96" term
   // in[0] < 2**64
   // out[3] < 2**29
   // out[4] < 2**29
   // out[1,2,5..7] < 2**28
 
-  (*out)[0] = static_cast<uint32>(in[0] & kBottom28Bits);
-  (*out)[1] += static_cast<uint32>((in[0] >> 28) & kBottom28Bits);
-  (*out)[2] += static_cast<uint32>(in[0] >> 56);
+  (*out)[0] = static_cast<uint32_t>(in[0] & kBottom28Bits);
+  (*out)[1] += static_cast<uint32_t>((in[0] >> 28) & kBottom28Bits);
+  (*out)[2] += static_cast<uint32_t>(in[0] >> 56);
   // out[0] < 2**28
   // out[1..4] < 2**29
   // out[5..7] < 2**28
@@ -170,11 +172,11 @@
 // out[i] < 2**29
 void Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) {
   LargeFieldElement tmp;
-  memset(&tmp, 0, sizeof(tmp));
+  SbMemorySet(&tmp, 0, sizeof(tmp));
 
   for (int i = 0; i < 8; i++) {
     for (int j = 0; j < 8; j++) {
-      tmp[i+j] += static_cast<uint64>(a[i]) * static_cast<uint64>(b[j]);
+      tmp[i + j] += static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(b[j]);
     }
   }
 
@@ -187,11 +189,11 @@
 // out[i] < 2**29
 void Square(FieldElement* out, const FieldElement& a) {
   LargeFieldElement tmp;
-  memset(&tmp, 0, sizeof(tmp));
+  SbMemorySet(&tmp, 0, sizeof(tmp));
 
   for (int i = 0; i < 8; i++) {
     for (int j = 0; j <= i; j++) {
-      uint64 r = static_cast<uint64>(a[i]) * static_cast<uint64>(a[j]);
+      uint64_t r = static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(a[j]);
       if (i == j) {
         tmp[i+j] += r;
       } else {
@@ -214,16 +216,16 @@
     a[i+1] += a[i] >> 28;
     a[i] &= kBottom28Bits;
   }
-  uint32 top = a[7] >> 28;
+  uint32_t top = a[7] >> 28;
   a[7] &= kBottom28Bits;
 
   // top < 2**4
   // Constant-time: mask = (top != 0) ? 0xffffffff : 0
-  uint32 mask = top;
+  uint32_t mask = top;
   mask |= mask >> 2;
   mask |= mask >> 1;
   mask <<= 31;
-  mask = static_cast<uint32>(static_cast<int32>(mask) >> 31);
+  mask = static_cast<uint32_t>(static_cast<int32_t>(mask) >> 31);
 
   // Eliminate top while maintaining the same value mod p.
   a[0] -= top;
@@ -300,7 +302,7 @@
     out[i+1] += out[i] >> 28;
     out[i] &= kBottom28Bits;
   }
-  uint32 top = out[7] >> 28;
+  uint32_t top = out[7] >> 28;
   out[7] &= kBottom28Bits;
 
   // Eliminate top while maintaining the same value mod p.
@@ -311,7 +313,7 @@
   // out[0] negative then we know that out[3] is sufficiently positive
   // because we just added to it.
   for (int i = 0; i < 3; i++) {
-    uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31);
+    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
     out[i] += (1 << 28) & mask;
     out[i+1] -= 1 & mask;
   }
@@ -344,7 +346,7 @@
   // As before, if we made out[0] negative then we know that out[3] is
   // sufficiently positive.
   for (int i = 0; i < 3; i++) {
-    uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31);
+    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
     out[i] += (1 << 28) & mask;
     out[i+1] -= 1 & mask;
   }
@@ -356,7 +358,7 @@
   // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones
   // ends up with any zero bits in the bottom 28 bits, then this wasn't
   // true.
-  uint32 top_4_all_ones = 0xffffffffu;
+  uint32_t top_4_all_ones = 0xffffffffu;
   for (int i = 4; i < 8; i++) {
     top_4_all_ones &= out[i];
   }
@@ -368,37 +370,39 @@
   top_4_all_ones &= top_4_all_ones >> 2;
   top_4_all_ones &= top_4_all_ones >> 1;
   top_4_all_ones =
-      static_cast<uint32>(static_cast<int32>(top_4_all_ones << 31) >> 31);
+      static_cast<uint32_t>(static_cast<int32_t>(top_4_all_ones << 31) >> 31);
 
   // Now we test whether the bottom three limbs are non-zero.
-  uint32 bottom_3_non_zero = out[0] | out[1] | out[2];
+  uint32_t bottom_3_non_zero = out[0] | out[1] | out[2];
   bottom_3_non_zero |= bottom_3_non_zero >> 16;
   bottom_3_non_zero |= bottom_3_non_zero >> 8;
   bottom_3_non_zero |= bottom_3_non_zero >> 4;
   bottom_3_non_zero |= bottom_3_non_zero >> 2;
   bottom_3_non_zero |= bottom_3_non_zero >> 1;
   bottom_3_non_zero =
-      static_cast<uint32>(static_cast<int32>(bottom_3_non_zero) >> 31);
+      static_cast<uint32_t>(static_cast<int32_t>(bottom_3_non_zero) >> 31);
 
   // Everything depends on the value of out[3].
   //    If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p
   //    If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0,
   //      then the whole value is >= p
   //    If it's < 0xffff000, then the whole value is < p
-  uint32 n = out[3] - 0xffff000;
-  uint32 out_3_equal = n;
+  uint32_t n = out[3] - 0xffff000;
+  uint32_t out_3_equal = n;
   out_3_equal |= out_3_equal >> 16;
   out_3_equal |= out_3_equal >> 8;
   out_3_equal |= out_3_equal >> 4;
   out_3_equal |= out_3_equal >> 2;
   out_3_equal |= out_3_equal >> 1;
   out_3_equal =
-      ~static_cast<uint32>(static_cast<int32>(out_3_equal << 31) >> 31);
+      ~static_cast<uint32_t>(static_cast<int32_t>(out_3_equal << 31) >> 31);
 
   // If out[3] > 0xffff000 then n's MSB will be zero.
-  uint32 out_3_gt = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31);
+  uint32_t out_3_gt =
+      ~static_cast<uint32_t>(static_cast<int32_t>(n << 31) >> 31);
 
-  uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
+  uint32_t mask =
+      top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
   out[0] -= 1 & mask;
   out[3] -= 0xffff000 & mask;
   out[4] -= 0xfffffff & mask;
@@ -421,7 +425,7 @@
   39211076, 180311059, 84673715, 188764328,
 };
 
-void CopyConditional(Point* out, const Point& a, uint32 mask);
+void CopyConditional(Point* out, const Point& a, uint32_t mask);
 void DoubleJacobian(Point* out, const Point& a);
 
 // AddJacobian computes *out = a+b where a != b.
@@ -431,13 +435,13 @@
   // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
   FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v;
 
-  uint32 z1_is_zero = IsZero(a.z);
-  uint32 z2_is_zero = IsZero(b.z);
+  uint32_t z1_is_zero = IsZero(a.z);
+  uint32_t z2_is_zero = IsZero(b.z);
 
-  // Z1Z1 = Z1**2
+  // Z1Z1 = Z1²
   Square(&z1z1, a.z);
 
-  // Z2Z2 = Z2**2
+  // Z2Z2 = Z2²
   Square(&z2z2, b.z);
 
   // U1 = X1*Z2Z2
@@ -457,11 +461,11 @@
   // H = U2-U1
   Subtract(&h, u2, u1);
   Reduce(&h);
-  uint32 x_equal = IsZero(h);
+  uint32_t x_equal = IsZero(h);
 
-  // I = (2*H)**2
-  for (int j = 0; j < 8; j++) {
-    i[j] = h[j] << 1;
+  // I = (2*H)²
+  for (int k = 0; k < 8; k++) {
+    i[k] = h[k] << 1;
   }
   Reduce(&i);
   Square(&i, i);
@@ -471,7 +475,7 @@
   // r = 2*(S2-S1)
   Subtract(&r, s2, s1);
   Reduce(&r);
-  uint32 y_equal = IsZero(r);
+  uint32_t y_equal = IsZero(r);
 
   if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
     // The two input points are the same therefore we must use the dedicated
@@ -480,15 +484,15 @@
     return;
   }
 
-  for (int i = 0; i < 8; i++) {
-    r[i] <<= 1;
+  for (int k = 0; k < 8; k++) {
+    r[k] <<= 1;
   }
   Reduce(&r);
 
   // V = U1*I
   Mul(&v, u1, i);
 
-  // Z3 = ((Z1+Z2)**2-Z1Z1-Z2Z2)*H
+  // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
   Add(&z1z1, z1z1, z2z2);
   Add(&z2z2, a.z, b.z);
   Reduce(&z2z2);
@@ -497,9 +501,9 @@
   Reduce(&out->z);
   Mul(&out->z, out->z, h);
 
-  // X3 = r**2-J-2*V
-  for (int i = 0; i < 8; i++) {
-    z1z1[i] = v[i] << 1;
+  // X3 = r²-J-2*V
+  for (int k = 0; k < 8; k++) {
+    z1z1[k] = v[k] << 1;
   }
   Add(&z1z1, j, z1z1);
   Reduce(&z1z1);
@@ -508,8 +512,8 @@
   Reduce(&out->x);
 
   // Y3 = r*(V-X3)-2*S1*J
-  for (int i = 0; i < 8; i++) {
-    s1[i] <<= 1;
+  for (int k = 0; k < 8; k++) {
+    s1[k] <<= 1;
   }
   Mul(&s1, s1, j);
   Subtract(&z1z1, v, out->x);
@@ -541,7 +545,7 @@
   Reduce(&alpha);
   Mul(&alpha, alpha, t);
 
-  // Z3 = (Y1+Z1)**2-gamma-delta
+  // Z3 = (Y1+Z1)²-gamma-delta
   Add(&out->z, a.y, a.z);
   Reduce(&out->z);
   Square(&out->z, out->z);
@@ -550,7 +554,7 @@
   Subtract(&out->z, out->z, delta);
   Reduce(&out->z);
 
-  // X3 = alpha**2-8*beta
+  // X3 = alpha²-8*beta
   for (int i = 0; i < 8; i++) {
           delta[i] = beta[i] << 3;
   }
@@ -559,7 +563,7 @@
   Subtract(&out->x, out->x, delta);
   Reduce(&out->x);
 
-  // Y3 = alpha*(4*beta-X3)-8*(gamma**2)
+  // Y3 = alpha*(4*beta-X3)-8*gamma²
   for (int i = 0; i < 8; i++) {
           beta[i] <<= 2;
   }
@@ -578,9 +582,7 @@
 
 // CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of
 // 0xffffffff.
-void CopyConditional(Point* out,
-                     const Point& a,
-                     uint32 mask) {
+void CopyConditional(Point* out, const Point& a, uint32_t mask) {
   for (int i = 0; i < 8; i++) {
     out->x[i] ^= mask & (a.x[i] ^ out->x[i]);
     out->y[i] ^= mask & (a.y[i] ^ out->y[i]);
@@ -590,15 +592,17 @@
 
 // ScalarMult calculates *out = a*scalar where scalar is a big-endian number of
 // length scalar_len and != 0.
-void ScalarMult(Point* out, const Point& a,
-                const uint8* scalar, size_t scalar_len) {
-  memset(out, 0, sizeof(*out));
+void ScalarMult(Point* out,
+                const Point& a,
+                const uint8_t* scalar,
+                size_t scalar_len) {
+  SbMemorySet(out, 0, sizeof(*out));
   Point tmp;
 
   for (size_t i = 0; i < scalar_len; i++) {
     for (unsigned int bit_num = 0; bit_num < 8; bit_num++) {
       DoubleJacobian(out, *out);
-      uint32 bit = static_cast<uint32>(static_cast<int32>(
+      uint32_t bit = static_cast<uint32_t>(static_cast<int32_t>(
           (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31));
       AddJacobian(&tmp, a, *out);
       CopyConditional(out, tmp, bit);
@@ -608,7 +612,7 @@
 
 // Get224Bits reads 7 words from in and scatters their contents in
 // little-endian form into 8 words at out, 28 bits per output word.
-void Get224Bits(uint32* out, const uint32* in) {
+void Get224Bits(uint32_t* out, const uint32_t* in) {
   out[0] = NetToHost32(in[6]) & kBottom28Bits;
   out[1] = ((NetToHost32(in[5]) << 4) |
             (NetToHost32(in[6]) >> 28)) & kBottom28Bits;
@@ -628,7 +632,7 @@
 // Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from
 // each of 8 input words and writing them in big-endian order to 7 words at
 // out.
-void Put224Bits(uint32* out, const uint32* in) {
+void Put224Bits(uint32_t* out, const uint32_t* in) {
   out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28));
   out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24));
   out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20));
@@ -638,22 +642,22 @@
   out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4));
 }
 
-} // anonymous namespace
+}  // anonymous namespace
 
 namespace crypto {
 
 namespace p224 {
 
-bool Point::SetFromString(const base::StringPiece& in) {
+bool Point::SetFromString(base::StringPiece in) {
   if (in.size() != 2*28)
     return false;
-  const uint32* inwords = reinterpret_cast<const uint32*>(in.data());
+  const uint32_t* inwords = reinterpret_cast<const uint32_t*>(in.data());
   Get224Bits(x, inwords);
   Get224Bits(y, inwords + 7);
-  memset(&z, 0, sizeof(z));
+  SbMemorySet(&z, 0, sizeof(z));
   z[0] = 1;
 
-  // Check that the point is on the curve, i.e. that y**2 = x**3 - 3x + b.
+  // Check that the point is on the curve, i.e. that y² = x³ - 3x + b.
   FieldElement lhs;
   Square(&lhs, y);
   Contract(&lhs);
@@ -672,11 +676,11 @@
 
   ::Add(&rhs, rhs, kB);
   Contract(&rhs);
-  return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
+  return SbMemoryCompare(&lhs, &rhs, sizeof(lhs)) == 0;
 }
 
 std::string Point::ToString() const {
-  FieldElement zinv, zinv_sq, x, y;
+  FieldElement zinv, zinv_sq, xx, yy;
 
   // If this is the point at infinity we return a string of all zeros.
   if (IsZero(this->z)) {
@@ -686,20 +690,20 @@
 
   Invert(&zinv, this->z);
   Square(&zinv_sq, zinv);
-  Mul(&x, this->x, zinv_sq);
+  Mul(&xx, x, zinv_sq);
   Mul(&zinv_sq, zinv_sq, zinv);
-  Mul(&y, this->y, zinv_sq);
+  Mul(&yy, y, zinv_sq);
 
-  Contract(&x);
-  Contract(&y);
+  Contract(&xx);
+  Contract(&yy);
 
-  uint32 outwords[14];
-  Put224Bits(outwords, x);
-  Put224Bits(outwords + 7, y);
+  uint32_t outwords[14];
+  Put224Bits(outwords, xx);
+  Put224Bits(outwords + 7, yy);
   return std::string(reinterpret_cast<const char*>(outwords), sizeof(outwords));
 }
 
-void ScalarMult(const Point& in, const uint8* scalar, Point* out) {
+void ScalarMult(const Point& in, const uint8_t* scalar, Point* out) {
   ::ScalarMult(out, in, scalar, 28);
 }
 
@@ -712,7 +716,7 @@
   {1, 0, 0, 0, 0, 0, 0, 0},
 };
 
-void ScalarBaseMult(const uint8* scalar, Point* out) {
+void ScalarBaseMult(const uint8_t* scalar, Point* out) {
   ::ScalarMult(out, kBasePoint, scalar, 28);
 }
 
@@ -734,7 +738,7 @@
   Subtract(&out->y, kP, y);
   Reduce(&out->y);
 
-  memset(&out->z, 0, sizeof(out->z));
+  SbMemorySet(&out->z, 0, sizeof(out->z));
   out->z[0] = 1;
 }
 
diff --git a/src/crypto/p224.h b/src/crypto/p224.h
index 769d791..6c6948e 100644
--- a/src/crypto/p224.h
+++ b/src/crypto/p224.h
@@ -7,9 +7,9 @@
 
 #include <string>
 
-#include "base/basictypes.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -17,21 +17,21 @@
 // in FIPS 186-3, section D.2.2.
 namespace p224 {
 
-// An element of the field (Z/pZ) is represented with 8, 28-bit limbs in
+// An element of the field (ℤ/pℤ) is represented with 8, 28-bit limbs in
 // little endian order.
-typedef uint32 FieldElement[8];
+typedef uint32_t FieldElement[8];
 
 struct CRYPTO_EXPORT Point {
   // SetFromString the value of the point from the 56 byte, external
   // representation. The external point representation is an (x, y) pair of a
   // point on the curve. Each field element is represented as a big-endian
   // number < p.
-  bool SetFromString(const base::StringPiece& in);
+  bool SetFromString(base::StringPiece in);
 
   // ToString returns an external representation of the Point.
   std::string ToString() const;
 
-  // An Point is represented in Jacobian form (x/(z**2), y/(z**3)).
+  // An Point is represented in Jacobian form (x/z², y/z³).
   FieldElement x, y, z;
 };
 
@@ -41,11 +41,13 @@
 
 // ScalarMult computes *out = in*scalar where scalar is a 28-byte, big-endian
 // number.
-void CRYPTO_EXPORT ScalarMult(const Point& in, const uint8* scalar, Point* out);
+void CRYPTO_EXPORT ScalarMult(const Point& in,
+                              const uint8_t* scalar,
+                              Point* out);
 
 // ScalarBaseMult computes *out = g*scalar where g is the base point of the
 // curve and scalar is a 28-byte, big-endian number.
-void CRYPTO_EXPORT ScalarBaseMult(const uint8* scalar, Point* out);
+void CRYPTO_EXPORT ScalarBaseMult(const uint8_t* scalar, Point* out);
 
 // Add computes *out = a+b.
 void CRYPTO_EXPORT Add(const Point& a, const Point& b, Point* out);
diff --git a/src/crypto/p224_spake.cc b/src/crypto/p224_spake.cc
index 31109a4..0515b3c 100644
--- a/src/crypto/p224_spake.cc
+++ b/src/crypto/p224_spake.cc
@@ -5,19 +5,24 @@
 // This code implements SPAKE2, a variant of EKE:
 //  http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04
 
-#include <crypto/p224_spake.h>
+#include "crypto/p224_spake.h"
 
-#include <base/logging.h>
-#include <crypto/p224.h>
-#include <crypto/random.h>
-#include <crypto/secure_util.h>
+#include <algorithm>
+
+#include "starboard/types.h"
+
+#include "starboard/memory.h"
+
+#include "base/logging.h"
+#include "crypto/p224.h"
+#include "crypto/random.h"
+#include "crypto/secure_util.h"
 
 namespace {
 
 // The following two points (M and N in the protocol) are verifiable random
 // points on the curve and can be generated with the following code:
 
-// #include <stdint.h>
 // #include <stdio.h>
 // #include <string.h>
 //
@@ -25,6 +30,9 @@
 // #include <openssl/obj_mac.h>
 // #include <openssl/sha.h>
 //
+// // Silence a presubmit.
+// #define PRINTF printf
+//
 // static const char kSeed1[] = "P224 point generation seed (M)";
 // static const char kSeed2[] = "P224 point generation seed (N)";
 //
@@ -50,7 +58,7 @@
 //       EC_POINT_get_affine_coordinates_GFp(p224, p, &x, &y, NULL);
 //       char* x_str = BN_bn2hex(&x);
 //       char* y_str = BN_bn2hex(&y);
-//       printf("Found after %u iterations:\n%s\n%s\n", i, x_str, y_str);
+//       PRINTF("Found after %u iterations:\n%s\n%s\n", i, x_str, y_str);
 //       OPENSSL_free(x_str);
 //       OPENSSL_free(y_str);
 //       BN_free(&x);
@@ -80,7 +88,7 @@
    33188520, 48266885, 177021753, 81038478},
   {104523827, 245682244, 266509668, 236196369,
    28372046, 145351378, 198520366, 113345994},
-  {1, 0, 0, 0, 0, 0, 0},
+  {1, 0, 0, 0, 0, 0, 0, 0},
 };
 
 const crypto::p224::Point kN = {
@@ -88,31 +96,34 @@
    5034302, 185981975, 171998428, 11653062},
   {197567436, 51226044, 60372156, 175772188,
    42075930, 8083165, 160827401, 65097570},
-  {1, 0, 0, 0, 0, 0, 0},
+  {1, 0, 0, 0, 0, 0, 0, 0},
 };
 
 }  // anonymous namespace
 
 namespace crypto {
 
-P224EncryptedKeyExchange::P224EncryptedKeyExchange(
-    PeerType peer_type, const base::StringPiece& password)
-    : state_(kStateInitial),
-      is_server_(peer_type == kPeerTypeServer) {
-  memset(&x_, 0, sizeof(x_));
-  memset(&expected_authenticator_, 0, sizeof(expected_authenticator_));
+P224EncryptedKeyExchange::P224EncryptedKeyExchange(PeerType peer_type,
+                                                   base::StringPiece password)
+    : state_(kStateInitial), is_server_(peer_type == kPeerTypeServer) {
+  SbMemorySet(&x_, 0, sizeof(x_));
+  SbMemorySet(&expected_authenticator_, 0, sizeof(expected_authenticator_));
 
   // x_ is a random scalar.
   RandBytes(x_, sizeof(x_));
 
-  // X = g**x_
-  p224::Point X;
-  p224::ScalarBaseMult(x_, &X);
-
   // Calculate |password| hash to get SPAKE password value.
   SHA256HashString(std::string(password.data(), password.length()),
                    pw_, sizeof(pw_));
 
+  Init();
+}
+
+void P224EncryptedKeyExchange::Init() {
+  // X = g**x_
+  p224::Point X;
+  p224::ScalarBaseMult(x_, &X);
+
   // The client masks the Diffie-Hellman value, X, by adding M**pw and the
   // server uses N**pw.
   p224::Point MNpw;
@@ -125,7 +136,7 @@
   next_message_ = Xstar.ToString();
 }
 
-const std::string& P224EncryptedKeyExchange::GetMessage() {
+const std::string& P224EncryptedKeyExchange::GetNextMessage() {
   if (state_ == kStateInitial) {
     state_ = kStateRecvDH;
     return next_message_;
@@ -134,14 +145,14 @@
     return next_message_;
   }
 
-  LOG(FATAL) << "P224EncryptedKeyExchange::GetMessage called in"
+  LOG(FATAL) << "P224EncryptedKeyExchange::GetNextMessage called in"
                 " bad state " << state_;
   next_message_ = "";
   return next_message_;
 }
 
 P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage(
-    const base::StringPiece& message) {
+    base::StringPiece message) {
   if (state_ == kStateRecvHash) {
     // This is the final state of the protocol: we are reading the peer's
     // authentication hash and checking that it matches the one that we expect.
@@ -197,18 +208,18 @@
 
   // Now we calculate the hashes that each side will use to prove to the other
   // that they derived the correct value for K.
-  uint8 client_hash[kSHA256Length], server_hash[kSHA256Length];
+  uint8_t client_hash[kSHA256Length], server_hash[kSHA256Length];
   CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_,
                 client_hash);
   CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_,
                 server_hash);
 
-  const uint8* my_hash = is_server_ ? server_hash : client_hash;
-  const uint8* their_hash = is_server_ ? client_hash : server_hash;
+  const uint8_t* my_hash = is_server_ ? server_hash : client_hash;
+  const uint8_t* their_hash = is_server_ ? client_hash : server_hash;
 
   next_message_ =
       std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length);
-  memcpy(expected_authenticator_, their_hash, kSHA256Length);
+  SbMemoryCopy(expected_authenticator_, their_hash, kSHA256Length);
   state_ = kStateSendHash;
   return kResultPending;
 }
@@ -218,7 +229,7 @@
     const std::string& client_masked_dh,
     const std::string& server_masked_dh,
     const std::string& k,
-    uint8* out_digest) {
+    uint8_t* out_digest) {
   std::string hash_contents;
 
   if (peer_type == kPeerTypeServer) {
@@ -240,9 +251,23 @@
   return error_;
 }
 
-const std::string& P224EncryptedKeyExchange::GetKey() {
+const std::string& P224EncryptedKeyExchange::GetKey() const {
   DCHECK_EQ(state_, kStateDone);
+  return GetUnverifiedKey();
+}
+
+const std::string& P224EncryptedKeyExchange::GetUnverifiedKey() const {
+  // Key is already final when state is kStateSendHash. Subsequent states are
+  // used only for verification of the key. Some users may combine verification
+  // with sending verifiable data instead of |expected_authenticator_|.
+  DCHECK_GE(state_, kStateSendHash);
   return key_;
 }
 
+void P224EncryptedKeyExchange::SetXForTesting(const std::string& x) {
+  SbMemorySet(&x_, 0, sizeof(x_));
+  SbMemoryCopy(&x_, x.data(), std::min(x.size(), sizeof(x_)));
+  Init();
+}
+
 }  // namespace crypto
diff --git a/src/crypto/p224_spake.h b/src/crypto/p224_spake.h
index 1711d56..1a5fcb0 100644
--- a/src/crypto/p224_spake.h
+++ b/src/crypto/p224_spake.h
@@ -5,16 +5,20 @@
 #ifndef CRYPTO_P224_SPAKE_H_
 #define CRYPTO_P224_SPAKE_H_
 
-#include <base/string_piece.h>
-#include <crypto/p224.h>
-#include <crypto/sha2.h>
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/strings/string_piece.h"
+#include "crypto/p224.h"
+#include "crypto/sha2.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
 // P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted
 // Key Exchange. It allows two parties that have a secret common
 // password to establish a common secure key by exchanging messages
-// over unsecure channel without disclosing the password.
+// over an insecure channel without disclosing the password.
 //
 // The password can be low entropy as authenticating with an attacker only
 // gives the attacker a one-shot password oracle. No other information about
@@ -22,10 +26,10 @@
 // permitted authentication attempts otherwise they get many one-shot oracles.)
 //
 // The protocol requires several RTTs (actually two, but you shouldn't assume
-// that.) To use the object, call GetMessage() and pass that message to the
+// that.) To use the object, call GetNextMessage() and pass that message to the
 // peer. Get a message from the peer and feed it into ProcessMessage. Then
 // examine the return value of ProcessMessage:
-//   kResultPending: Another round is required. Call GetMessage and repeat.
+//   kResultPending: Another round is required. Call GetNextMessage and repeat.
 //   kResultFailed: The authentication has failed. You can get a human readable
 //       error message by calling error().
 //   kResultSuccess: The authentication was successful.
@@ -51,16 +55,15 @@
   // password: secret session password. Both parties to the
   //     authentication must pass the same value. For the case of a
   //     TLS connection, see RFC 5705.
-  P224EncryptedKeyExchange(PeerType peer_type,
-                           const base::StringPiece& password);
+  P224EncryptedKeyExchange(PeerType peer_type, base::StringPiece password);
 
-  // GetMessage returns a byte string which must be passed to the other party
-  // in the authentication.
-  const std::string& GetMessage();
+  // GetNextMessage returns a byte string which must be passed to the other
+  // party in the authentication.
+  const std::string& GetNextMessage();
 
   // ProcessMessage processes a message which must have been generated by a
-  // call to GetMessage() by the other party.
-  Result ProcessMessage(const base::StringPiece& message);
+  // call to GetNextMessage() by the other party.
+  Result ProcessMessage(base::StringPiece message);
 
   // In the event that ProcessMessage() returns kResultFailed, error will
   // return a human readable error message.
@@ -68,7 +71,11 @@
 
   // The key established as result of the key exchange. Must be called
   // at then end after ProcessMessage() returns kResultSuccess.
-  const std::string& GetKey();
+  const std::string& GetKey() const;
+
+  // The key established as result of the key exchange. Can be called after
+  // the first ProcessMessage()
+  const std::string& GetUnverifiedKey() const;
 
  private:
   // The authentication state machine is very simple and each party proceeds
@@ -81,30 +88,36 @@
     kStateDone,
   };
 
+  FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues);
+
+  void Init();
+
+  // Sets internal random scalar. Should be used by tests only.
+  void SetXForTesting(const std::string& x);
+
   State state_;
   const bool is_server_;
-  // next_message_ contains a value for GetMessage() to return.
+  // next_message_ contains a value for GetNextMessage() to return.
   std::string next_message_;
   std::string error_;
 
   // CalculateHash computes the verification hash for the given peer and writes
   // |kSHA256Length| bytes at |out_digest|.
-  void CalculateHash(
-      PeerType peer_type,
-      const std::string& client_masked_dh,
-      const std::string& server_masked_dh,
-      const std::string& k,
-      uint8* out_digest);
+  void CalculateHash(PeerType peer_type,
+                     const std::string& client_masked_dh,
+                     const std::string& server_masked_dh,
+                     const std::string& k,
+                     uint8_t* out_digest);
 
   // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc
   // file).
-  uint8 x_[p224::kScalarBytes];
-  // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32,
-  // big-endian length prefix (see paper refereneced in .cc file).
-  uint8 pw_[p224::kScalarBytes];
+  uint8_t x_[p224::kScalarBytes];
+  // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32_t,
+  // big-endian length prefix (see paper referenced in .cc file).
+  uint8_t pw_[p224::kScalarBytes];
   // expected_authenticator_ is used to store the hash value expected from the
   // other party.
-  uint8 expected_authenticator_[kSHA256Length];
+  uint8_t expected_authenticator_[kSHA256Length];
 
   std::string key_;
 };
diff --git a/src/crypto/p224_spake_unittest.cc b/src/crypto/p224_spake_unittest.cc
index eabc843..db15e33 100644
--- a/src/crypto/p224_spake_unittest.cc
+++ b/src/crypto/p224_spake_unittest.cc
@@ -2,45 +2,54 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <crypto/p224_spake.h>
+#include "crypto/p224_spake.h"
+
+#include <string>
 
 #include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace crypto {
 
 namespace {
 
-bool RunExchange(P224EncryptedKeyExchange* client,
-                 P224EncryptedKeyExchange* server) {
+std::string HexEncodeString(const std::string& binary_data) {
+  return base::HexEncode(binary_data.c_str(), binary_data.size());
+}
 
+bool RunExchange(P224EncryptedKeyExchange* client,
+                 P224EncryptedKeyExchange* server,
+                 bool is_password_same) {
   for (;;) {
     std::string client_message, server_message;
-    client_message = client->GetMessage();
-    server_message = server->GetMessage();
+    client_message = client->GetNextMessage();
+    server_message = server->GetNextMessage();
 
     P224EncryptedKeyExchange::Result client_result, server_result;
     client_result = client->ProcessMessage(server_message);
     server_result = server->ProcessMessage(client_message);
 
     // Check that we never hit the case where only one succeeds.
-    if ((client_result == P224EncryptedKeyExchange::kResultSuccess) ^
-        (server_result == P224EncryptedKeyExchange::kResultSuccess)) {
-      CHECK(false) << "Parties differ on whether authentication was successful";
-    }
+    EXPECT_EQ(client_result == P224EncryptedKeyExchange::kResultSuccess,
+              server_result == P224EncryptedKeyExchange::kResultSuccess);
 
     if (client_result == P224EncryptedKeyExchange::kResultFailed ||
         server_result == P224EncryptedKeyExchange::kResultFailed) {
       return false;
     }
 
+    EXPECT_EQ(is_password_same,
+              client->GetUnverifiedKey() == server->GetUnverifiedKey());
+
     if (client_result == P224EncryptedKeyExchange::kResultSuccess &&
         server_result == P224EncryptedKeyExchange::kResultSuccess) {
       return true;
     }
 
-    CHECK_EQ(P224EncryptedKeyExchange::kResultPending, client_result);
-    CHECK_EQ(P224EncryptedKeyExchange::kResultPending, server_result);
+    EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, client_result);
+    EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, server_result);
   }
 }
 
@@ -54,7 +63,7 @@
   P224EncryptedKeyExchange server(
       P224EncryptedKeyExchange::kPeerTypeServer, kPassword);
 
-  EXPECT_TRUE(RunExchange(&client, &server));
+  EXPECT_TRUE(RunExchange(&client, &server, true));
   EXPECT_EQ(client.GetKey(), server.GetKey());
 }
 
@@ -66,7 +75,43 @@
       P224EncryptedKeyExchange::kPeerTypeServer,
       "wrongpassword");
 
-  EXPECT_FALSE(RunExchange(&client, &server));
+  EXPECT_FALSE(RunExchange(&client, &server, false));
+}
+
+TEST(MutualAuth, ExpectedValues) {
+  P224EncryptedKeyExchange client(P224EncryptedKeyExchange::kPeerTypeClient,
+                                  kPassword);
+  client.SetXForTesting("Client x");
+  P224EncryptedKeyExchange server(P224EncryptedKeyExchange::kPeerTypeServer,
+                                  kPassword);
+  server.SetXForTesting("Server x");
+
+  std::string client_message = client.GetNextMessage();
+  EXPECT_EQ(
+      "3508EF7DECC8AB9F9C439FBB0154288BBECC0A82E8448F4CF29554EB"
+      "BE9D486686226255EAD1D077C635B1A41F46AC91D7F7F32CED9EC3E0",
+      HexEncodeString(client_message));
+
+  std::string server_message = server.GetNextMessage();
+  EXPECT_EQ(
+      "A3088C18B75D2C2B107105661AEC85424777475EB29F1DDFB8C14AFB"
+      "F1603D0DF38413A00F420ACF2059E7997C935F5A957A193D09A2B584",
+      HexEncodeString(server_message));
+
+  EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
+            client.ProcessMessage(server_message));
+  EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
+            server.ProcessMessage(client_message));
+
+  EXPECT_EQ(client.GetUnverifiedKey(), server.GetUnverifiedKey());
+  // Must stay the same. External implementations should be able to pair with.
+  EXPECT_EQ(
+      "CE7CCFC435CDA4F01EC8826788B1F8B82EF7D550A34696B371096E64"
+      "C487D4FE193F7D1A6FF6820BC7F807796BA3889E8F999BBDEFC32FFA",
+      HexEncodeString(server.GetUnverifiedKey()));
+
+  EXPECT_TRUE(RunExchange(&client, &server, true));
+  EXPECT_EQ(client.GetKey(), server.GetKey());
 }
 
 TEST(MutualAuth, Fuzz) {
@@ -80,16 +125,16 @@
 
     // We'll only be testing small values of i, but we don't want that to bias
     // the test coverage. So we disperse the value of i by multiplying by the
-    // FNV, 32-bit prime, producing a poor-man's PRNG.
-    const uint32 rand = i * 16777619;
+    // FNV, 32-bit prime, producing a simplistic PRNG.
+    const uint32_t rand = i * 16777619;
 
     for (unsigned round = 0;; round++) {
       std::string client_message, server_message;
-      client_message = client.GetMessage();
-      server_message = server.GetMessage();
+      client_message = client.GetNextMessage();
+      server_message = server.GetNextMessage();
 
       if ((rand & 1) == round) {
-        const bool server_or_client = (rand & 2) != 0;
+        const bool server_or_client = rand & 2;
         std::string* m = server_or_client ? &server_message : &client_message;
         if (rand & 4) {
           // Truncate
diff --git a/src/crypto/p224_unittest.cc b/src/crypto/p224_unittest.cc
index aaf5f59..126b50d 100644
--- a/src/crypto/p224_unittest.cc
+++ b/src/crypto/p224_unittest.cc
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "crypto/p224.h"
 
+#include "base/macros.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace crypto {
@@ -14,22 +17,20 @@
 using p224::Point;
 
 // kBasePointExternal is the P224 base point in external representation.
-static const uint8 kBasePointExternal[56] = {
-  0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f,
-  0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
-  0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
-  0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88,
-  0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
-  0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
-  0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34,
+static const uint8_t kBasePointExternal[56] = {
+    0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9,
+    0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+    0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
+    0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+    0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34,
 };
 
 // TestVector represents a test of scalar multiplication of the base point.
 // |scalar| is a big-endian scalar and |affine| is the external representation
 // of g*scalar.
 struct TestVector {
-  uint8 scalar[28];
-  uint8 affine[28*2];
+  uint8_t scalar[28];
+  uint8_t affine[28 * 2];
 };
 
 static const int kNumNISTTestVectors = 52;
@@ -777,8 +778,8 @@
   const std::string external = point.ToString();
 
   ASSERT_EQ(external.size(), 56u);
-  EXPECT_TRUE(memcmp(external.data(), kBasePointExternal,
-                     sizeof(kBasePointExternal)) == 0);
+  EXPECT_EQ(0, SbMemoryCompare(external.data(), kBasePointExternal,
+                               sizeof(kBasePointExternal)));
 }
 
 TEST(P224, ScalarBaseMult) {
@@ -788,8 +789,8 @@
     p224::ScalarBaseMult(kNISTTestVectors[i].scalar, &point);
     const std::string external = point.ToString();
     ASSERT_EQ(external.size(), 56u);
-    EXPECT_TRUE(memcmp(external.data(), kNISTTestVectors[i].affine,
-                       external.size()) == 0);
+    EXPECT_EQ(0, SbMemoryCompare(external.data(), kNISTTestVectors[i].affine,
+                                 external.size()));
   }
 }
 
@@ -803,19 +804,19 @@
 
   p224::Negate(b, &minus_b);
   p224::Add(a, b, &sum);
-  EXPECT_TRUE(memcmp(&sum, &a, sizeof(sum)) != 0);
+  EXPECT_NE(0, SbMemoryCompare(&sum, &a, sizeof(sum)));
   p224::Add(minus_b, sum, &a_again);
-  EXPECT_TRUE(a_again.ToString() == a.ToString());
+  EXPECT_EQ(a_again.ToString(), a.ToString());
 }
 
 TEST(P224, Infinity) {
   char zeros[56];
-  memset(zeros, 0, sizeof(zeros));
+  SbMemorySet(zeros, 0, sizeof(zeros));
 
   // Test that x^0 = ∞.
   Point a;
-  p224::ScalarBaseMult(reinterpret_cast<const uint8*>(zeros), &a);
-  EXPECT_TRUE(memcmp(zeros, a.ToString().data(), sizeof(zeros)) == 0);
+  p224::ScalarBaseMult(reinterpret_cast<const uint8_t*>(zeros), &a);
+  EXPECT_EQ(0, SbMemoryCompare(zeros, a.ToString().data(), sizeof(zeros)));
 
   // We shouldn't allow ∞ to be imported.
   EXPECT_FALSE(a.SetFromString(std::string(zeros, sizeof(zeros))));
diff --git a/src/crypto/random.cc b/src/crypto/random.cc
index a19bb1a..daa6481 100644
--- a/src/crypto/random.cc
+++ b/src/crypto/random.cc
@@ -5,6 +5,7 @@
 #include "crypto/random.h"
 
 #include "base/rand_util.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
diff --git a/src/crypto/random.h b/src/crypto/random.h
index 002616b..e646201 100644
--- a/src/crypto/random.h
+++ b/src/crypto/random.h
@@ -5,9 +5,8 @@
 #ifndef CRYPTO_RANDOM_H_
 #define CRYPTO_RANDOM_H_
 
-#include <stddef.h>
-
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -18,4 +17,4 @@
 
 }
 
-#endif
+#endif  // CRYPTO_RANDOM_H_
diff --git a/src/crypto/random_unittest.cc b/src/crypto/random_unittest.cc
index 297f3cc..8ff0915 100644
--- a/src/crypto/random_unittest.cc
+++ b/src/crypto/random_unittest.cc
@@ -4,7 +4,10 @@
 
 #include "crypto/random.h"
 
-#include "base/string_util.h"
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 // Basic functionality tests. Does NOT test the security of the random data.
@@ -22,6 +25,6 @@
 
 TEST(RandBytes, RandBytes) {
   std::string bytes(16, '\0');
-  crypto::RandBytes(WriteInto(&bytes, bytes.size()), bytes.size());
+  crypto::RandBytes(base::WriteInto(&bytes, bytes.size()), bytes.size());
   EXPECT_TRUE(!IsTrivial(bytes));
 }
diff --git a/src/crypto/rsa_private_key.cc b/src/crypto/rsa_private_key.cc
index 62eb996..d84e460 100644
--- a/src/crypto/rsa_private_key.cc
+++ b/src/crypto/rsa_private_key.cc
@@ -4,380 +4,108 @@
 
 #include "crypto/rsa_private_key.h"
 
-#include <algorithm>
-#include <list>
+#include <memory>
+#include <utility>
 
 #include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_util.h"
-
-// This file manually encodes and decodes RSA private keys using PrivateKeyInfo
-// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are:
-//
-// PrivateKeyInfo ::= SEQUENCE {
-//   version Version,
-//   privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
-//   privateKey PrivateKey,
-//   attributes [0] IMPLICIT Attributes OPTIONAL
-// }
-//
-// RSAPrivateKey ::= SEQUENCE {
-//   version Version,
-//   modulus INTEGER,
-//   publicExponent INTEGER,
-//   privateExponent INTEGER,
-//   prime1 INTEGER,
-//   prime2 INTEGER,
-//   exponent1 INTEGER,
-//   exponent2 INTEGER,
-//   coefficient INTEGER
-// }
-
-namespace {
-// Helper for error handling during key import.
-#define READ_ASSERT(truth) \
-  if (!(truth)) { \
-    NOTREACHED(); \
-    return false; \
-  }
-}  // namespace
+#include "crypto/openssl_util.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/bn.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
 
 namespace crypto {
 
-const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = {
-  0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
-  0x05, 0x00
-};
+// static
+std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
-PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
-    : big_endian_(big_endian) {}
+  bssl::UniquePtr<RSA> rsa_key(RSA_new());
+  bssl::UniquePtr<BIGNUM> bn(BN_new());
+  if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
+    return nullptr;
 
-PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
+  if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr))
+    return nullptr;
 
-bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) {
-  std::list<uint8> content;
+  std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+  result->key_.reset(EVP_PKEY_new());
+  if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get()))
+    return nullptr;
 
-  // Version (always zero)
-  uint8 version = 0;
-
-  PrependInteger(coefficient_, &content);
-  PrependInteger(exponent2_, &content);
-  PrependInteger(exponent1_, &content);
-  PrependInteger(prime2_, &content);
-  PrependInteger(prime1_, &content);
-  PrependInteger(private_exponent_, &content);
-  PrependInteger(public_exponent_, &content);
-  PrependInteger(modulus_, &content);
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-  PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
-
-  // RSA algorithm OID
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everying into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
+  return result;
 }
 
-bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) {
-  // Create a sequence with the modulus (n) and public exponent (e).
-  std::vector<uint8> bit_string;
-  if (!ExportPublicKey(&bit_string))
-    return false;
+// static
+std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo(
+    const std::vector<uint8_t>& input) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
-  // Add the sequence as the contents of a bit string.
-  std::list<uint8> content;
-  PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
-                   &content);
+  CBS cbs;
+  CBS_init(&cbs, input.data(), input.size());
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
+  if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA)
+    return nullptr;
 
-  // Add the RSA algorithm OID.
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  // Finally, wrap everything in a sequence.
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everything into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
+  std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+  result->key_ = std::move(pkey);
+  return result;
 }
 
-bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) {
-  // Create a sequence with the modulus (n) and public exponent (e).
-  std::list<uint8> content;
-  PrependInteger(&public_exponent_[0],
-                 static_cast<int>(public_exponent_.size()),
-                 &content);
-  PrependInteger(&modulus_[0],  static_cast<int>(modulus_.size()), &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everything into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
+// static
+std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) {
+  DCHECK(key);
+  if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA)
+    return nullptr;
+  std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
+  copy->key_ = bssl::UpRef(key);
+  return copy;
 }
 
-bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) {
-  if (input.empty()) {
+RSAPrivateKey::RSAPrivateKey() = default;
+
+RSAPrivateKey::~RSAPrivateKey() = default;
+
+std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Copy() const {
+  std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
+  bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get()));
+  if (!rsa)
+    return nullptr;
+  copy->key_.reset(EVP_PKEY_new());
+  if (!EVP_PKEY_set1_RSA(copy->key_.get(), rsa.get()))
+    return nullptr;
+  return copy;
+}
+
+bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  uint8_t *der;
+  size_t der_len;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_private_key(cbb.get(), key_.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
   }
-
-  // Parse the private key info up to the public key values, ignoring
-  // the subsequent private key values.
-  uint8* src = const_cast<uint8*>(&input.front());
-  uint8* end = src + input.size();
-  if (!ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadAlgorithmIdentifier(&src, end) ||
-      !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
-      !ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadInteger(&src, end, &modulus_))
-    return false;
-
-  int mod_size = modulus_.size();
-  READ_ASSERT(mod_size % 2 == 0);
-  int primes_size = mod_size / 2;
-
-  if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
-    return false;
-
-  READ_ASSERT(src == end);
-
-
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
   return true;
 }
 
-void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8>& in,
-                                         std::list<uint8>* out) {
-  uint8* ptr = const_cast<uint8*>(&in.front());
-  PrependIntegerImpl(ptr, in.size(), out, big_endian_);
-}
-
-// Helper to prepend an ASN.1 integer.
-void PrivateKeyInfoCodec::PrependInteger(uint8* val,
-                                         int num_bytes,
-                                         std::list<uint8>* data) {
-  PrependIntegerImpl(val, num_bytes, data, big_endian_);
-}
-
-void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val,
-                                             int num_bytes,
-                                             std::list<uint8>* data,
-                                             bool big_endian) {
- // Reverse input if little-endian.
- std::vector<uint8> tmp;
- if (!big_endian) {
-   tmp.assign(val, val + num_bytes);
-   std::reverse(tmp.begin(), tmp.end());
-   val = &tmp.front();
- }
-
-  // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
-  // from the most-significant end of the integer.
-  int start = 0;
-  while (start < (num_bytes - 1) && val[start] == 0x00) {
-    start++;
-    num_bytes--;
-  }
-  PrependBytes(val, start, num_bytes, data);
-
-  // ASN.1 integers are signed. To encode a positive integer whose sign bit
-  // (the most significant bit) would otherwise be set and make the number
-  // negative, ASN.1 requires a leading null byte to force the integer to be
-  // positive.
-  uint8 front = data->front();
-  if ((front & 0x80) != 0) {
-    data->push_front(0x00);
-    num_bytes++;
-  }
-
-  PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
-}
-
-bool PrivateKeyInfoCodec::ReadInteger(uint8** pos,
-                                      uint8* end,
-                                      std::vector<uint8>* out) {
-  return ReadIntegerImpl(pos, end, out, big_endian_);
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos,
-                                                      uint8* end,
-                                                      size_t expected_size,
-                                                      std::vector<uint8>* out) {
-  std::vector<uint8> temp;
-  if (!ReadIntegerImpl(pos, end, &temp, true))  // Big-Endian
+bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  uint8_t *der;
+  size_t der_len;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_public_key(cbb.get(), key_.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
-
-  int pad = expected_size - temp.size();
-  int index = 0;
-  if (out->size() == expected_size + 1) {
-    READ_ASSERT(out->front() == 0x00);
-    pad++;
-    index++;
-  } else {
-    READ_ASSERT(out->size() <= expected_size);
   }
-
-  out->insert(out->end(), pad, 0x00);
-  out->insert(out->end(), temp.begin(), temp.end());
-
-  // Reverse output if little-endian.
-  if (!big_endian_)
-    std::reverse(out->begin(), out->end());
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos,
-                                          uint8* end,
-                                          std::vector<uint8>* out,
-                                          bool big_endian) {
-  uint32 length = 0;
-  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
-    return false;
-
-  // The first byte can be zero to force positiveness. We can ignore this.
-  if (**pos == 0x00) {
-    ++(*pos);
-    --length;
-  }
-
-  if (length)
-    out->insert(out->end(), *pos, (*pos) + length);
-
-  (*pos) += length;
-
-  // Reverse output if little-endian.
-  if (!big_endian)
-    std::reverse(out->begin(), out->end());
-  return true;
-}
-
-void PrivateKeyInfoCodec::PrependBytes(uint8* val,
-                                       int start,
-                                       int num_bytes,
-                                       std::list<uint8>* data) {
-  while (num_bytes > 0) {
-    --num_bytes;
-    data->push_front(val[start + num_bytes]);
-  }
-}
-
-void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8>* data) {
-  // The high bit is used to indicate whether additional octets are needed to
-  // represent the length.
-  if (size < 0x80) {
-    data->push_front(static_cast<uint8>(size));
-  } else {
-    uint8 num_bytes = 0;
-    while (size > 0) {
-      data->push_front(static_cast<uint8>(size & 0xFF));
-      size >>= 8;
-      num_bytes++;
-    }
-    CHECK_LE(num_bytes, 4);
-    data->push_front(0x80 | num_bytes);
-  }
-}
-
-void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type,
-                                                     uint32 length,
-                                                     std::list<uint8>* output) {
-  PrependLength(length, output);
-  output->push_front(type);
-}
-
-void PrivateKeyInfoCodec::PrependBitString(uint8* val,
-                                           int num_bytes,
-                                           std::list<uint8>* output) {
-  // Start with the data.
-  PrependBytes(val, 0, num_bytes, output);
-  // Zero unused bits.
-  output->push_front(0);
-  // Add the length.
-  PrependLength(num_bytes + 1, output);
-  // Finally, add the bit string tag.
-  output->push_front((uint8) kBitStringTag);
-}
-
-bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) {
-  READ_ASSERT(*pos < end);
-  int length = 0;
-
-  // If the MSB is not set, the length is just the byte itself.
-  if (!(**pos & 0x80)) {
-    length = **pos;
-    (*pos)++;
-  } else {
-    // Otherwise, the lower 7 indicate the length of the length.
-    int length_of_length = **pos & 0x7F;
-    READ_ASSERT(length_of_length <= 4);
-    (*pos)++;
-    READ_ASSERT(*pos + length_of_length < end);
-
-    length = 0;
-    for (int i = 0; i < length_of_length; ++i) {
-      length <<= 8;
-      length |= **pos;
-      (*pos)++;
-    }
-  }
-
-  READ_ASSERT(*pos + length <= end);
-  if (result) *result = length;
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos,
-                                                  uint8* end,
-                                                  uint8 expected_tag,
-                                                  uint32* length) {
-  READ_ASSERT(*pos < end);
-  READ_ASSERT(**pos == expected_tag);
-  (*pos)++;
-
-  return ReadLength(pos, end, length);
-}
-
-bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) {
-  return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
-}
-
-bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) {
-  READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
-  READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
-                     sizeof(kRsaAlgorithmIdentifier)) == 0);
-  (*pos) += sizeof(kRsaAlgorithmIdentifier);
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) {
-  uint32 length = 0;
-  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
-    return false;
-
-  // The version should be zero.
-  for (uint32 i = 0; i < length; ++i) {
-    READ_ASSERT(**pos == 0x00);
-    (*pos)++;
-  }
-
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
   return true;
 }
 
diff --git a/src/crypto/rsa_private_key.h b/src/crypto/rsa_private_key.h
index ff368d8..2c6d4e8 100644
--- a/src/crypto/rsa_private_key.h
+++ b/src/crypto/rsa_private_key.h
@@ -5,170 +5,17 @@
 #ifndef CRYPTO_RSA_PRIVATE_KEY_H_
 #define CRYPTO_RSA_PRIVATE_KEY_H_
 
-#include "build/build_config.h"
-
-#if defined(USE_OPENSSL)
-// Forward declaration for openssl/*.h
-typedef struct evp_pkey_st EVP_PKEY;
-#elif defined(USE_NSS)
-// Forward declaration.
-struct SECKEYPrivateKeyStr;
-struct SECKEYPublicKeyStr;
-#elif defined(OS_IOS)
-#include <Security/Security.h>
-#elif defined(OS_MACOSX)
-#include <Security/cssm.h>
-#endif
-
-#include <list>
+#include <memory>
 #include <vector>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
+#include "build/build_config.h"
 #include "crypto/crypto_export.h"
-
-#if defined(OS_WIN)
-#include "crypto/scoped_capi_types.h"
-#endif
-#if defined(USE_NSS)
-#include "base/gtest_prod_util.h"
-#endif
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/base.h"
 
 namespace crypto {
 
-// Used internally by RSAPrivateKey for serializing and deserializing
-// PKCS #8 PrivateKeyInfo and PublicKeyInfo.
-class PrivateKeyInfoCodec {
- public:
-
-  // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
-  static const uint8 kRsaAlgorithmIdentifier[];
-
-  // ASN.1 tags for some types we use.
-  static const uint8 kBitStringTag = 0x03;
-  static const uint8 kIntegerTag = 0x02;
-  static const uint8 kNullTag = 0x05;
-  static const uint8 kOctetStringTag = 0x04;
-  static const uint8 kSequenceTag = 0x30;
-
-  // |big_endian| here specifies the byte-significance of the integer components
-  // that will be parsed & serialized (modulus(), etc...) during Import(),
-  // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the
-  // PrivateKeyInfo/PublicKeyInfo (which is always big-endian).
-  explicit PrivateKeyInfoCodec(bool big_endian);
-
-  ~PrivateKeyInfoCodec();
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the PrivateKeyInfo structure to |output|.
-  bool Export(std::vector<uint8>* output);
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the PublicKeyInfo structure to |output|.
-  bool ExportPublicKeyInfo(std::vector<uint8>* output);
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the RSAPublicKey structure to |output|.
-  bool ExportPublicKey(std::vector<uint8>* output);
-
-  // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
-  // and populates the integer components with |big_endian_| byte-significance.
-  // IMPORTANT NOTE: This is currently *not* security-approved for importing
-  // keys from unstrusted sources.
-  bool Import(const std::vector<uint8>& input);
-
-  // Accessors to the contents of the integer components of the PrivateKeyInfo
-  // structure.
-  std::vector<uint8>* modulus() { return &modulus_; };
-  std::vector<uint8>* public_exponent() { return &public_exponent_; };
-  std::vector<uint8>* private_exponent() { return &private_exponent_; };
-  std::vector<uint8>* prime1() { return &prime1_; };
-  std::vector<uint8>* prime2() { return &prime2_; };
-  std::vector<uint8>* exponent1() { return &exponent1_; };
-  std::vector<uint8>* exponent2() { return &exponent2_; };
-  std::vector<uint8>* coefficient() { return &coefficient_; };
-
- private:
-  // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_|
-  // value.
-  void PrependInteger(const std::vector<uint8>& in, std::list<uint8>* out);
-  void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data);
-
-  // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian|
-  // byte-significance into |data| as an ASN.1 integer.
-  void PrependIntegerImpl(uint8* val,
-                          int num_bytes,
-                          std::list<uint8>* data,
-                          bool big_endian);
-
-  // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_|
-  // value.
-  bool ReadInteger(uint8** pos, uint8* end, std::vector<uint8>* out);
-  bool ReadIntegerWithExpectedSize(uint8** pos,
-                                   uint8* end,
-                                   size_t expected_size,
-                                   std::vector<uint8>* out);
-
-  // Reads an ASN.1 integer from |pos|, and stores the result into |out| with
-  // |big_endian| byte-significance.
-  bool ReadIntegerImpl(uint8** pos,
-                       uint8* end,
-                       std::vector<uint8>* out,
-                       bool big_endian);
-
-  // Prepends the integer stored in |val|, starting a index |start|, for
-  // |num_bytes| bytes onto |data|.
-  void PrependBytes(uint8* val,
-                    int start,
-                    int num_bytes,
-                    std::list<uint8>* data);
-
-  // Helper to prepend an ASN.1 length field.
-  void PrependLength(size_t size, std::list<uint8>* data);
-
-  // Helper to prepend an ASN.1 type header.
-  void PrependTypeHeaderAndLength(uint8 type,
-                                  uint32 length,
-                                  std::list<uint8>* output);
-
-  // Helper to prepend an ASN.1 bit string
-  void PrependBitString(uint8* val, int num_bytes, std::list<uint8>* output);
-
-  // Read an ASN.1 length field. This also checks that the length does not
-  // extend beyond |end|.
-  bool ReadLength(uint8** pos, uint8* end, uint32* result);
-
-  // Read an ASN.1 type header and its length.
-  bool ReadTypeHeaderAndLength(uint8** pos,
-                               uint8* end,
-                               uint8 expected_tag,
-                               uint32* length);
-
-  // Read an ASN.1 sequence declaration. This consumes the type header and
-  // length field, but not the contents of the sequence.
-  bool ReadSequence(uint8** pos, uint8* end);
-
-  // Read the RSA AlgorithmIdentifier.
-  bool ReadAlgorithmIdentifier(uint8** pos, uint8* end);
-
-  // Read one of the two version fields in PrivateKeyInfo.
-  bool ReadVersion(uint8** pos, uint8* end);
-
-  // The byte-significance of the stored components (modulus, etc..).
-  bool big_endian_;
-
-  // Component integers of the PrivateKeyInfo
-  std::vector<uint8> modulus_;
-  std::vector<uint8> public_exponent_;
-  std::vector<uint8> private_exponent_;
-  std::vector<uint8> prime1_;
-  std::vector<uint8> prime2_;
-  std::vector<uint8> exponent1_;
-  std::vector<uint8> exponent2_;
-  std::vector<uint8> coefficient_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec);
-};
-
 // Encapsulates an RSA private key. Can be used to generate new keys, export
 // keys to other formats, or to extract a public key.
 // TODO(hclam): This class should be ref-counted so it can be reused easily.
@@ -177,104 +24,35 @@
   ~RSAPrivateKey();
 
   // Create a new random instance. Can return NULL if initialization fails.
-  static RSAPrivateKey* Create(uint16 num_bits);
-
-  // Create a new random instance. Can return NULL if initialization fails.
-  // The created key is permanent and is not exportable in plaintext form.
-  //
-  // NOTE: Currently only available if USE_NSS is defined.
-  static RSAPrivateKey* CreateSensitive(uint16 num_bits);
+  static std::unique_ptr<RSAPrivateKey> Create(uint16_t num_bits);
 
   // Create a new instance by importing an existing private key. The format is
   // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if
   // initialization fails.
-  static RSAPrivateKey* CreateFromPrivateKeyInfo(
-      const std::vector<uint8>& input);
+  static std::unique_ptr<RSAPrivateKey> CreateFromPrivateKeyInfo(
+      const std::vector<uint8_t>& input);
 
-  // Create a new instance by importing an existing private key. The format is
-  // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if
-  // initialization fails.
-  // The created key is permanent and is not exportable in plaintext form.
-  //
-  // NOTE: Currently only available if USE_NSS is defined.
-  static RSAPrivateKey* CreateSensitiveFromPrivateKeyInfo(
-      const std::vector<uint8>& input);
+  // Create a new instance from an existing EVP_PKEY, taking a
+  // reference to it. |key| must be an RSA key. Returns NULL on
+  // failure.
+  static std::unique_ptr<RSAPrivateKey> CreateFromKey(EVP_PKEY* key);
 
-  // Import an existing public key, and then search for the private
-  // half in the key database. The format of the public key blob is is
-  // an X509 SubjectPublicKeyInfo block. This can return NULL if
-  // initialization fails or the private key cannot be found.  The
-  // caller takes ownership of the returned object, but nothing new is
-  // created in the key database.
-  //
-  // NOTE: Currently only available if USE_NSS is defined.
-  static RSAPrivateKey* FindFromPublicKeyInfo(
-      const std::vector<uint8>& input);
-
-#if defined(USE_OPENSSL)
-  EVP_PKEY* key() { return key_; }
-#elif defined(USE_NSS)
-  SECKEYPrivateKeyStr* key() { return key_; }
-  SECKEYPublicKeyStr* public_key() { return public_key_; }
-#elif defined(OS_WIN)
-  HCRYPTPROV provider() { return provider_; }
-  HCRYPTKEY key() { return key_; }
-#elif defined(OS_IOS)
-  SecKeyRef key() { return key_; }
-  SecKeyRef public_key() { return public_key_; }
-#elif defined(OS_MACOSX)
-  CSSM_KEY_PTR key() { return &key_; }
-  CSSM_KEY_PTR public_key() { return &public_key_; }
-#endif
+  EVP_PKEY* key() { return key_.get(); }
 
   // Creates a copy of the object.
-  RSAPrivateKey* Copy() const;
+  std::unique_ptr<RSAPrivateKey> Copy() const;
 
-  // Exports the private key to a PKCS #1 PrivateKey block.
-  bool ExportPrivateKey(std::vector<uint8>* output) const;
+  // Exports the private key to a PKCS #8 PrivateKeyInfo block.
+  bool ExportPrivateKey(std::vector<uint8_t>* output) const;
 
   // Exports the public key to an X509 SubjectPublicKeyInfo block.
-  bool ExportPublicKey(std::vector<uint8>* output) const;
+  bool ExportPublicKey(std::vector<uint8_t>* output) const;
 
  private:
-#if defined(USE_NSS)
-  FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FindFromPublicKey);
-  FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey);
-#endif
-
-  // Constructor is private. Use one of the Create*() or Find*()
-  // methods above instead.
+  // Constructor is private. Use one of the Create*() methods above instead.
   RSAPrivateKey();
 
-  // Shared helper for Create() and CreateSensitive().
-  // TODO(cmasone): consider replacing |permanent| and |sensitive| with a
-  //                flags arg created by ORing together some enumerated values.
-  static RSAPrivateKey* CreateWithParams(uint16 num_bits,
-                                         bool permanent,
-                                         bool sensitive);
-
-  // Shared helper for CreateFromPrivateKeyInfo() and
-  // CreateSensitiveFromPrivateKeyInfo().
-  static RSAPrivateKey* CreateFromPrivateKeyInfoWithParams(
-      const std::vector<uint8>& input, bool permanent, bool sensitive);
-
-#if defined(USE_OPENSSL)
-  EVP_PKEY* key_;
-#elif defined(USE_NSS)
-  SECKEYPrivateKeyStr* key_;
-  SECKEYPublicKeyStr* public_key_;
-#elif defined(OS_WIN)
-  bool InitProvider();
-
-  ScopedHCRYPTPROV provider_;
-  ScopedHCRYPTKEY key_;
-#elif defined(OS_IOS)
-  SecKeyRef key_;
-  SecKeyRef public_key_;
-#elif defined(OS_MACOSX)
-  CSSM_KEY key_;
-  CSSM_KEY public_key_;
-#endif
+  bssl::UniquePtr<EVP_PKEY> key_;
 
   DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey);
 };
diff --git a/src/crypto/rsa_private_key_ios.cc b/src/crypto/rsa_private_key_ios.cc
deleted file mode 100644
index d96b3e9..0000000
--- a/src/crypto/rsa_private_key_ios.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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 "crypto/rsa_private_key.h"
-
-#include "base/logging.h"
-
-namespace crypto {
-
-// |RSAPrivateKey| is not used on iOS. This implementation was written so that
-// it would compile. It may be possible to use the NSS implementation as a real
-// implementation, but it hasn't yet been necessary.
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {}
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (public_key_)
-    CFRelease(public_key_);
-  if (key_)
-    CFRelease(key_);
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-}  // namespace base
diff --git a/src/crypto/rsa_private_key_mac.cc b/src/crypto/rsa_private_key_mac.cc
deleted file mode 100644
index fbe1491..0000000
--- a/src/crypto/rsa_private_key_mac.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2012 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/rsa_private_key.h"
-
-#include <list>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/cssm_init.h"
-
-namespace crypto {
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  CSSM_CC_HANDLE cc_handle;
-  CSSM_RETURN crtn;
-  crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA,
-                                      num_bits, NULL, NULL, NULL, NULL, NULL,
-                                      &cc_handle);
-  if (crtn) {
-    NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
-    return NULL;
-  }
-
-  CSSM_DATA label = { 9,
-      const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) };
-  crtn = CSSM_GenerateKeyPair(cc_handle,
-      CSSM_KEYUSE_VERIFY,
-      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label,
-      result->public_key(), CSSM_KEYUSE_SIGN,
-      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL,
-      result->key());
-  CSSM_DeleteContext(cc_handle);
-  if (crtn) {
-    NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
-    return NULL;
-  }
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  if (input.empty())
-    return NULL;
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  CSSM_KEY key;
-  memset(&key, 0, sizeof(key));
-  key.KeyData.Data = const_cast<uint8*>(&input.front());
-  key.KeyData.Length = input.size();
-  key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
-  key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
-  key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
-  key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
-  key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
-  key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
-  key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
-
-  CSSM_KEY_SIZE key_size;
-  CSSM_RETURN crtn;
-  crtn = CSSM_QueryKeySizeInBits(
-      GetSharedCSPHandle(), CSSM_INVALID_HANDLE, &key, &key_size);
-  if (crtn) {
-    NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
-    return NULL;
-  }
-  key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
-
-  // Perform a NULL unwrap operation on the key so that result's key_
-  // instance variable points to a key that can be released via CSSM_FreeKey().
-  CSSM_ACCESS_CREDENTIALS creds;
-  memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-  CSSM_CC_HANDLE cc_handle;
-  crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE,
-      CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle);
-  if (crtn) {
-    NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn;
-    return NULL;
-  }
-  CSSM_DATA label_data, desc_data = { 0, NULL };
-  label_data.Data =
-      const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped"));
-  label_data.Length = 9;
-  crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY,
-      CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data,
-      NULL, result->key(), &desc_data);
-  if (crtn) {
-    NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn;
-    return NULL;
-  }
-
-  // Extract a public key from the private key.
-  // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key
-  // format when attempting to generate certs, so use PKCS1 instead.
-  PrivateKeyInfoCodec codec(true);
-  std::vector<uint8> private_key_data;
-  private_key_data.assign(key.KeyData.Data,
-                          key.KeyData.Data + key.KeyData.Length);
-  if (!codec.Import(private_key_data)) {
-    return NULL;
-  }
-  std::vector<uint8> public_key_data;
-  if (!codec.ExportPublicKey(&public_key_data)) {
-    return NULL;
-  }
-
-  CSSM_KEY* public_key = result->public_key();
-  size_t size = public_key_data.size();
-  public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size));
-  if (!public_key->KeyData.Data) {
-    NOTREACHED() << "CSSMMalloc failed";
-    return NULL;
-  }
-  memcpy(public_key->KeyData.Data, &public_key_data.front(), size);
-  public_key->KeyData.Length = size;
-  public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
-  public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
-  public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
-  public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
-  public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
-  public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
-  public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
-
-  crtn = CSSM_QueryKeySizeInBits(
-      GetSharedCSPHandle(), CSSM_INVALID_HANDLE, public_key, &key_size);
-  if (crtn) {
-    DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn;
-    return NULL;
-  }
-  public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-RSAPrivateKey::RSAPrivateKey() {
-  memset(&key_, 0, sizeof(key_));
-  memset(&public_key_, 0, sizeof(public_key_));
-
-  EnsureCSSMInit();
-}
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (key_.KeyData.Data) {
-    CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE);
-  }
-  if (public_key_.KeyData.Data) {
-    CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE);
-  }
-}
-
-RSAPrivateKey* RSAPrivateKey::Copy() const {
-  std::vector<uint8> key_bytes;
-  if (!ExportPrivateKey(&key_bytes))
-    return NULL;
-  return CreateFromPrivateKeyInfo(key_bytes);
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
-  if (!key_.KeyData.Data || !key_.KeyData.Length) {
-    return false;
-  }
-  output->clear();
-  output->insert(output->end(), key_.KeyData.Data,
-                 key_.KeyData.Data + key_.KeyData.Length);
-  return true;
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
-  PrivateKeyInfoCodec private_key_info(true);
-  std::vector<uint8> private_key_data;
-  private_key_data.assign(key_.KeyData.Data,
-                          key_.KeyData.Data + key_.KeyData.Length);
-  return (private_key_info.Import(private_key_data) &&
-          private_key_info.ExportPublicKeyInfo(output));
-}
-
-}  // namespace crypto
diff --git a/src/crypto/rsa_private_key_nss.cc b/src/crypto/rsa_private_key_nss.cc
deleted file mode 100644
index 3b8bd44..0000000
--- a/src/crypto/rsa_private_key_nss.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// 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 "crypto/rsa_private_key.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <pk11pub.h>
-#include <secmod.h>
-
-#include <list>
-
-#include "base/debug/leak_annotations.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_util.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/scoped_nss_types.h"
-
-// TODO(rafaelw): Consider refactoring common functions and definitions from
-// rsa_private_key_win.cc or using NSS's ASN.1 encoder.
-namespace {
-
-static bool ReadAttribute(SECKEYPrivateKey* key,
-                          CK_ATTRIBUTE_TYPE type,
-                          std::vector<uint8>* output) {
-  SECItem item;
-  SECStatus rv;
-  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  output->assign(item.data, item.data + item.len);
-  SECITEM_FreeItem(&item, PR_FALSE);
-  return true;
-}
-
-}  // namespace
-
-namespace crypto {
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (key_)
-    SECKEY_DestroyPrivateKey(key_);
-  if (public_key_)
-    SECKEY_DestroyPublicKey(public_key_);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
-  return CreateWithParams(num_bits,
-                          PR_FALSE /* not permanent */,
-                          PR_FALSE /* not sensitive */);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
-  return CreateWithParams(num_bits,
-                          PR_TRUE /* permanent */,
-                          PR_TRUE /* sensitive */);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  return CreateFromPrivateKeyInfoWithParams(input,
-                                            PR_FALSE /* not permanent */,
-                                            PR_FALSE /* not sensitive */);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  return CreateFromPrivateKeyInfoWithParams(input,
-                                            PR_TRUE /* permanent */,
-                                            PR_TRUE /* sensitive */);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
-    const std::vector<uint8>& input) {
-  EnsureNSSInit();
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  // First, decode and save the public key.
-  SECItem key_der;
-  key_der.type = siBuffer;
-  key_der.data = const_cast<unsigned char*>(&input[0]);
-  key_der.len = input.size();
-
-  CERTSubjectPublicKeyInfo* spki =
-      SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
-  if (!spki) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  result->public_key_ = SECKEY_ExtractPublicKey(spki);
-  SECKEY_DestroySubjectPublicKeyInfo(spki);
-  if (!result->public_key_) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  // Make sure the key is an RSA key.  If not, that's an error
-  if (result->public_key_->keyType != rsaKey) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  ScopedSECItem ck_id(
-      PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
-  if (!ck_id.get()) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  // Search all slots in all modules for the key with the given ID.
-  AutoSECMODListReadLock auto_lock;
-  SECMODModuleList* head = SECMOD_GetDefaultModuleList();
-  for (SECMODModuleList* item = head; item != NULL; item = item->next) {
-    int slot_count = item->module->loaded ? item->module->slotCount : 0;
-    for (int i = 0; i < slot_count; i++) {
-      // Finally...Look for the key!
-      result->key_ = PK11_FindKeyByKeyID(item->module->slots[i],
-                                         ck_id.get(), NULL);
-      if (result->key_)
-        return result.release();
-    }
-  }
-
-  // We didn't find the key.
-  return NULL;
-}
-
-RSAPrivateKey* RSAPrivateKey::Copy() const {
-  RSAPrivateKey* copy = new RSAPrivateKey();
-  copy->key_ = SECKEY_CopyPrivateKey(key_);
-  copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
-  return copy;
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
-  PrivateKeyInfoCodec private_key_info(true);
-
-  // Manually read the component attributes of the private key and build up
-  // the PrivateKeyInfo.
-  if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
-      !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
-          private_key_info.public_exponent()) ||
-      !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
-          private_key_info.private_exponent()) ||
-      !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
-      !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
-      !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
-      !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
-      !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
-    NOTREACHED();
-    return false;
-  }
-
-  return private_key_info.Export(output);
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
-  ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
-  if (!der_pubkey.get()) {
-    NOTREACHED();
-    return false;
-  }
-
-  output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
-  return true;
-}
-
-RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
-  EnsureNSSInit();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits,
-                                               bool permanent,
-                                               bool sensitive) {
-  EnsureNSSInit();
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  ScopedPK11Slot slot(GetPrivateNSSKeySlot());
-  if (!slot.get())
-    return NULL;
-
-  PK11RSAGenParams param;
-  param.keySizeInBits = num_bits;
-  param.pe = 65537L;
-  result->key_ = PK11_GenerateKeyPair(slot.get(),
-                                      CKM_RSA_PKCS_KEY_PAIR_GEN,
-                                      &param,
-                                      &result->public_key_,
-                                      permanent,
-                                      sensitive,
-                                      NULL);
-  if (!result->key_)
-    return NULL;
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
-    const std::vector<uint8>& input, bool permanent, bool sensitive) {
-  // This method currently leaks some memory.
-  // See http://crbug.com/34742.
-  ANNOTATE_SCOPED_MEMORY_LEAK;
-  EnsureNSSInit();
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
-  ScopedPK11Slot slot(GetPrivateNSSKeySlot());
-  if (!slot.get())
-    return NULL;
-
-  SECItem der_private_key_info;
-  der_private_key_info.data = const_cast<unsigned char*>(&input.front());
-  der_private_key_info.len = input.size();
-  // Allow the private key to be used for key unwrapping, data decryption,
-  // and signature generation.
-  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
-                                 KU_DIGITAL_SIGNATURE;
-  SECStatus rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
-      slot.get(), &der_private_key_info, NULL, NULL, permanent, sensitive,
-      key_usage, &result->key_, NULL);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
-  if (!result->public_key_) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-}  // namespace crypto
diff --git a/src/crypto/rsa_private_key_openssl.cc b/src/crypto/rsa_private_key_openssl.cc
deleted file mode 100644
index 0061db1..0000000
--- a/src/crypto/rsa_private_key_openssl.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// 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 "crypto/rsa_private_key.h"
-
-#include <openssl/evp.h>
-#include <openssl/pkcs12.h>
-#include <openssl/rsa.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/openssl_util.h"
-
-namespace crypto {
-
-namespace {
-
-// Function pointer definition, for injecting the required key export function
-// into ExportKey, below. The supplied function should export EVP_PKEY into
-// the supplied BIO, returning 1 on success or 0 on failure.
-typedef int (ExportFunction)(BIO*, EVP_PKEY*);
-
-// Helper to export |key| into |output| via the specified ExportFunction.
-bool ExportKey(EVP_PKEY* key,
-               ExportFunction export_fn,
-               std::vector<uint8>* output) {
-  if (!key)
-    return false;
-
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem()));
-
-  int res = export_fn(bio.get(), key);
-  if (!res)
-    return false;
-
-  char* data = NULL;
-  long len = BIO_get_mem_data(bio.get(), &data);
-  if (!data || len < 0)
-    return false;
-
-  output->assign(data, data + len);
-  return true;
-}
-
-}  // namespace
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
-  ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new());
-  ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new());
-  if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
-    return NULL;
-
-  if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL))
-    return NULL;
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-  result->key_ = EVP_PKEY_new();
-  if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get()))
-    return NULL;
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  if (input.empty())
-    return NULL;
-
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
-  char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0]));
-  ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size()));
-  if (!bio.get())
-    return NULL;
-
-  // Importing is a little more involved than exporting, as we must first
-  // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key
-  // Info structure returned.
-  ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf(
-      d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
-  if (!p8inf.get())
-    return NULL;
-
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-  result->key_ = EVP_PKCS82PKEY(p8inf.get());
-  if (!result->key_)
-    return NULL;
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-RSAPrivateKey::RSAPrivateKey()
-    : key_(NULL) {
-}
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (key_)
-    EVP_PKEY_free(key_);
-}
-
-RSAPrivateKey* RSAPrivateKey::Copy() const {
-  scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey());
-  bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_));
-  if (!rsa)
-    return NULL;
-  copy->key_ = EVP_PKEY_new();
-  if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get()))
-    return NULL;
-  return copy.release();
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
-  return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output);
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
-  return ExportKey(key_, i2d_PUBKEY_bio, output);
-}
-
-}  // namespace crypto
diff --git a/src/crypto/rsa_private_key_unittest.cc b/src/crypto/rsa_private_key_unittest.cc
index b981bda..27e8419 100644
--- a/src/crypto/rsa_private_key_unittest.cc
+++ b/src/crypto/rsa_private_key_unittest.cc
@@ -4,192 +4,203 @@
 
 #include "crypto/rsa_private_key.h"
 
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(STARBOARD)
+#include "starboard/client_porting/poem/string_poem.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
+#endif
+
 namespace {
 
-const uint8 kTestPrivateKeyInfo[] = {
-  0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30,
-  0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
-  0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01,
-  0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b,
-  0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
-  0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08,
-  0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64,
-  0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
-  0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a,
-  0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f,
-  0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
-  0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17,
-  0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5,
-  0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
-  0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85,
-  0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9,
-  0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
-  0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18,
-  0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93,
-  0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
-  0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89,
-  0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb,
-  0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7,
-  0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd,
-  0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95,
-  0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6,
-  0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc,
-  0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e,
-  0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b,
-  0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed,
-  0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa,
-  0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38,
-  0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee,
-  0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e,
-  0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e,
-  0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46,
-  0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00,
-  0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c,
-  0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7,
-  0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82,
-  0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89,
-  0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42,
-  0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8,
-  0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2,
-  0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81,
-  0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1,
-  0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72,
-  0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f,
-  0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62,
-  0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c,
-  0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c,
-  0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6,
-  0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b,
-  0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04,
-  0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9,
-  0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda,
-  0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58,
-  0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93,
-  0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae,
-  0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35,
-  0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17,
-  0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41,
-  0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30,
-  0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1,
-  0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0,
-  0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d,
-  0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd,
-  0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69,
-  0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39,
-  0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7,
-  0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f,
-  0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35,
-  0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99,
-  0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6,
-  0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3,
-  0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb,
-  0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca,
-  0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3,
-  0xb1, 0xc5, 0x15, 0xf3
-};
+const uint8_t kTestPrivateKeyInfo[] = {
+    0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+    0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+    0x00, 0xb8, 0x7f, 0x2b, 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
+    0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, 0x55, 0x84, 0xd5, 0x3a,
+    0xbf, 0x2b, 0xa4, 0x64, 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
+    0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, 0xb0, 0x40, 0x53, 0x3a,
+    0xd7, 0x66, 0x09, 0x0f, 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
+    0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, 0xde, 0x4e, 0xb9, 0x57,
+    0x5e, 0x7e, 0x0a, 0xe5, 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
+    0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, 0x84, 0x32, 0x33, 0xf3,
+    0x17, 0x49, 0xbf, 0xe9, 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
+    0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, 0x53, 0x56, 0xa6, 0x83,
+    0xa2, 0xce, 0x93, 0x93, 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
+    0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, 0x37, 0xcb, 0xf2, 0x98,
+    0xa0, 0xce, 0xb4, 0xcb, 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7,
+    0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, 0xed, 0xb8, 0x48, 0x8b,
+    0x16, 0x93, 0x36, 0x95, 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6,
+    0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, 0x43, 0x78, 0xf9, 0xfe,
+    0x1f, 0x33, 0x23, 0x1e, 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b,
+    0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, 0x86, 0xb2, 0xcb, 0x3c,
+    0xfe, 0x4e, 0xa1, 0xfa, 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38,
+    0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, 0xa3, 0xf6, 0x85, 0x6b,
+    0x84, 0x43, 0xc9, 0x1e, 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e,
+    0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, 0x29, 0x5c, 0xc0, 0x4f,
+    0x01, 0x02, 0x41, 0x00, 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c,
+    0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, 0xcc, 0x61, 0xcd, 0x38,
+    0x42, 0x20, 0xd3, 0x82, 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89,
+    0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, 0xba, 0x16, 0x1a, 0xea,
+    0x15, 0xc6, 0xf0, 0xb8, 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2,
+    0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, 0x02, 0x41, 0x00, 0xc0,
+    0x60, 0x62, 0x80, 0xe1, 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72,
+    0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, 0x7d, 0xd6, 0xb8, 0x31,
+    0x2b, 0x84, 0x7f, 0x62, 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c,
+    0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, 0x5c, 0x09, 0x3c, 0xcf,
+    0x2f, 0x44, 0x9d, 0xb6, 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b,
+    0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, 0xe2, 0x0e, 0x56, 0xca,
+    0x03, 0x1a, 0xc0, 0xf9, 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda,
+    0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, 0xda, 0x55, 0x98, 0x74,
+    0xfc, 0x28, 0x17, 0x93, 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae,
+    0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, 0xb8, 0x06, 0x03, 0xba,
+    0x08, 0x59, 0x2b, 0x17, 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41,
+    0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, 0xa0, 0x24, 0xf5, 0xdb,
+    0x2f, 0xf0, 0x2f, 0xf1, 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0,
+    0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, 0xb4, 0x14, 0xd4, 0x09,
+    0x91, 0x33, 0x5a, 0xfd, 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69,
+    0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, 0xff, 0x6e, 0xeb, 0xc6,
+    0x86, 0xf5, 0xb4, 0xc7, 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f,
+    0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, 0x3e, 0x70, 0x8a, 0xbf,
+    0x27, 0x49, 0xb0, 0x99, 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6,
+    0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, 0xc6, 0xa4, 0x92, 0xd1,
+    0xce, 0x6c, 0x72, 0xfb, 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca,
+    0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, 0xb1, 0xc5, 0x15, 0xf3};
 
 }  // namespace
 
 // Generate random private keys with two different sizes. Reimport, then
 // export them again. We should get back the same exact bytes.
 TEST(RSAPrivateKeyUnitTest, InitRandomTest) {
-  scoped_ptr<crypto::RSAPrivateKey> keypair1(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair1(
       crypto::RSAPrivateKey::Create(1024));
-  scoped_ptr<crypto::RSAPrivateKey> keypair2(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair2(
       crypto::RSAPrivateKey::Create(2048));
   ASSERT_TRUE(keypair1.get());
   ASSERT_TRUE(keypair2.get());
 
-  std::vector<uint8> privkey1;
-  std::vector<uint8> privkey2;
-  std::vector<uint8> pubkey1;
-  std::vector<uint8> pubkey2;
+  std::vector<uint8_t> privkey1;
+  std::vector<uint8_t> privkey2;
+  std::vector<uint8_t> pubkey1;
+  std::vector<uint8_t> pubkey2;
 
   ASSERT_TRUE(keypair1->ExportPrivateKey(&privkey1));
   ASSERT_TRUE(keypair2->ExportPrivateKey(&privkey2));
   ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1));
   ASSERT_TRUE(keypair2->ExportPublicKey(&pubkey2));
 
-  scoped_ptr<crypto::RSAPrivateKey> keypair3(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair3(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey1));
-  scoped_ptr<crypto::RSAPrivateKey> keypair4(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair4(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey2));
   ASSERT_TRUE(keypair3.get());
   ASSERT_TRUE(keypair4.get());
 
-  std::vector<uint8> privkey3;
-  std::vector<uint8> privkey4;
+  std::vector<uint8_t> privkey3;
+  std::vector<uint8_t> privkey4;
   ASSERT_TRUE(keypair3->ExportPrivateKey(&privkey3));
   ASSERT_TRUE(keypair4->ExportPrivateKey(&privkey4));
 
   ASSERT_EQ(privkey1.size(), privkey3.size());
   ASSERT_EQ(privkey2.size(), privkey4.size());
-  ASSERT_TRUE(0 == memcmp(&privkey1.front(), &privkey3.front(),
-                          privkey1.size()));
-  ASSERT_TRUE(0 == memcmp(&privkey2.front(), &privkey4.front(),
-                          privkey2.size()));
+  ASSERT_EQ(0, SbMemoryCompare(&privkey1.front(), &privkey3.front(),
+                               privkey1.size()));
+  ASSERT_EQ(0, SbMemoryCompare(&privkey2.front(), &privkey4.front(),
+                               privkey2.size()));
 }
 
 // Test Copy() method.
 TEST(RSAPrivateKeyUnitTest, CopyTest) {
-  std::vector<uint8> input(
-      kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
 
-  scoped_ptr<crypto::RSAPrivateKey> key(
+  std::unique_ptr<crypto::RSAPrivateKey> key(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
 
-  scoped_ptr<crypto::RSAPrivateKey> key_copy(key->Copy());
+  std::unique_ptr<crypto::RSAPrivateKey> key_copy(key->Copy());
   ASSERT_TRUE(key_copy.get());
 
-  std::vector<uint8> privkey_copy;
+  std::vector<uint8_t> privkey_copy;
   ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy));
   ASSERT_EQ(input, privkey_copy);
 }
 
+// Test that CreateFromPrivateKeyInfo fails if there is extra data after the RSA
+// key.
+TEST(RSAPrivateKeyUnitTest, ExtraData) {
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+  input.push_back(0);
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+
+  // Import should fail.
+  EXPECT_FALSE(key);
+}
+
+TEST(RSAPrivateKeyUnitTest, NotRsaKey) {
+  // Defines a valid P-256 private key.
+  const uint8_t kTestEcPrivateKeyInfo[] = {
+      0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
+      0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+      0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20,
+      0x1F, 0xE3, 0x39, 0x50, 0xC5, 0xF4, 0x61, 0x12, 0x4A, 0xE9, 0x92, 0xC2,
+      0xBD, 0xFD, 0xF1, 0xC7, 0x3B, 0x16, 0x15, 0xF5, 0x71, 0xBD, 0x56, 0x7E,
+      0x60, 0xD1, 0x9A, 0xA1, 0xF4, 0x8C, 0xDF, 0x42, 0xA1, 0x44, 0x03, 0x42,
+      0x00, 0x04, 0x7C, 0x11, 0x0C, 0x66, 0xDC, 0xFD, 0xA8, 0x07, 0xF6, 0xE6,
+      0x9E, 0x45, 0xDD, 0xB3, 0xC7, 0x4F, 0x69, 0xA1, 0x48, 0x4D, 0x20, 0x3E,
+      0x8D, 0xC5, 0xAD, 0xA8, 0xE9, 0xA9, 0xDD, 0x7C, 0xB3, 0xC7, 0x0D, 0xF4,
+      0x48, 0x98, 0x6E, 0x51, 0xBD, 0xE5, 0xD1, 0x57, 0x6F, 0x99, 0x90, 0x1F,
+      0x9C, 0x2C, 0x6A, 0x80, 0x6A, 0x47, 0xFD, 0x90, 0x76, 0x43, 0xA7, 0x2B,
+      0x83, 0x55, 0x97, 0xEF, 0xC8, 0xC6};
+
+  std::vector<uint8_t> input(
+      kTestEcPrivateKeyInfo,
+      kTestEcPrivateKeyInfo + sizeof(kTestEcPrivateKeyInfo));
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+
+  // Import should fail as the given PKCS8 bytes were for an EC key not RSA key.
+  EXPECT_FALSE(key);
+}
 
 // Verify that generated public keys look good. This test data was generated
 // with the openssl command line tool.
 TEST(RSAPrivateKeyUnitTest, PublicKeyTest) {
-  const uint8 expected_public_key_info[] = {
-    0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
-    0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
-    0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b,
-    0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
-    0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08,
-    0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64,
-    0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
-    0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a,
-    0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f,
-    0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
-    0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17,
-    0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5,
-    0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
-    0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85,
-    0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9,
-    0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
-    0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18,
-    0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93,
-    0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
-    0x00, 0x01
-  };
+  const uint8_t expected_public_key_info[] = {
+      0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+      0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+      0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, 0x20, 0xdc, 0x7c, 0x9b,
+      0x0c, 0xdc, 0x51, 0x61, 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08,
+      0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, 0x85, 0x7b, 0x0c, 0x04,
+      0x13, 0x3f, 0x8d, 0xf4, 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a,
+      0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, 0x9e, 0x36, 0x74, 0x30,
+      0xda, 0x8a, 0x31, 0x4f, 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17,
+      0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, 0xb2, 0x65, 0x7a, 0x89,
+      0x4e, 0xb6, 0x47, 0xff, 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85,
+      0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, 0x96, 0xd0, 0xd6, 0x14,
+      0x6f, 0x13, 0x8d, 0xc5, 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18,
+      0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, 0xe7, 0x1f, 0x0f, 0xe6,
+      0x0f, 0x02, 0x03, 0x01, 0x00, 0x01};
 
-  std::vector<uint8> input(
-      kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
 
-  scoped_ptr<crypto::RSAPrivateKey> key(
+  std::unique_ptr<crypto::RSAPrivateKey> key(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
   ASSERT_TRUE(key.get());
 
-  std::vector<uint8> output;
+  std::vector<uint8_t> output;
   ASSERT_TRUE(key->ExportPublicKey(&output));
 
-  ASSERT_TRUE(
-      memcmp(expected_public_key_info, &output.front(), output.size()) == 0);
+  ASSERT_EQ(0, SbMemoryCompare(expected_public_key_info, &output.front(),
+                               output.size()));
 }
 
 // These two test keys each contain an integer that has 0x00 for its most
@@ -207,199 +218,167 @@
 //
 // This test case verifies these two failures modes don't occur.
 TEST(RSAPrivateKeyUnitTest, ShortIntegers) {
-  const uint8 short_integer_with_high_bit[] = {
-    0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, 
-    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 
-    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 
-    0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 
-    0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, 
-    0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, 
-    0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, 
-    0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, 
-    0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, 
-    0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, 
-    0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, 
-    0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, 
-    0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, 
-    0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, 
-    0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, 
-    0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, 
-    0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, 
-    0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, 
-    0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, 
-    0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, 
-    0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, 
-    0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, 
-    0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, 
-    0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, 
-    0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, 
-    0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, 
-    0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, 
-    0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, 
-    0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, 
-    0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, 
-    0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, 
-    0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, 
-    0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, 
-    0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, 
-    0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, 
-    0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, 
-    0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, 
-    0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, 
-    0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, 
-    0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, 
-    0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, 
-    0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, 
-    0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, 
-    0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, 
-    0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, 
-    0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, 
-    0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, 
-    0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, 
-    0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, 
-    0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, 
-    0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, 
-    0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, 
-    0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, 
-    0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, 
-    0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, 
-    0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, 
-    0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, 
-    0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, 
-    0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, 
-    0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, 
-    0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, 
-    0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, 
-    0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, 
-    0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, 
-    0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, 
-    0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, 
-    0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, 
-    0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, 
-    0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, 
-    0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, 
-    0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, 
-    0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, 
-    0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, 
-    0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, 
-    0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, 
-    0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, 
-    0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, 
-    0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, 
-    0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, 
-    0x45, 0x84, 0xb0
-  };
+  const uint8_t short_integer_with_high_bit[] = {
+      0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+      0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+      0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+      0x00, 0x92, 0x59, 0x32, 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67,
+      0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, 0xda, 0xe1, 0xa3, 0x1e,
+      0x40, 0x01, 0x14, 0x5c, 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4,
+      0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, 0xf4, 0x53, 0x9f, 0xb8,
+      0xe0, 0x83, 0x93, 0xd1, 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f,
+      0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, 0x1f, 0xc1, 0x20, 0xb0,
+      0x70, 0xb2, 0x3b, 0xea, 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39,
+      0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, 0x12, 0xa4, 0x42, 0x26,
+      0x6c, 0x6e, 0x79, 0x70, 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81,
+      0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, 0x04, 0x58, 0xf5, 0x6b,
+      0xc9, 0xf1, 0xb5, 0x65, 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01,
+      0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, 0xb6, 0x59, 0x1d, 0xdc,
+      0x36, 0xb6, 0x60, 0x36, 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16,
+      0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, 0x68, 0x8f, 0xc5, 0xf8,
+      0xe2, 0x5d, 0xb3, 0x19, 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a,
+      0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, 0x30, 0x98, 0xb1, 0xf7,
+      0xbd, 0x14, 0x9a, 0x57, 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef,
+      0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, 0x54, 0x17, 0x25, 0x5b,
+      0x37, 0xe3, 0x35, 0x63, 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43,
+      0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, 0xda, 0xd7, 0x6f, 0xd2,
+      0x18, 0xbd, 0x39, 0xf1, 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e,
+      0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, 0xc1, 0x91, 0xec, 0xb8,
+      0x01, 0x02, 0x41, 0x00, 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f,
+      0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, 0x96, 0x8d, 0x22, 0x7b,
+      0x78, 0x73, 0xea, 0xbb, 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50,
+      0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, 0xa8, 0xca, 0x54, 0x41,
+      0xe8, 0xce, 0xbe, 0x7d, 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69,
+      0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, 0x02, 0x41, 0x00, 0xbd,
+      0x1e, 0xfe, 0x51, 0x99, 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c,
+      0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, 0x4c, 0xae, 0xa6, 0x41,
+      0x1c, 0xf0, 0x10, 0x37, 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d,
+      0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, 0x05, 0x98, 0x6b, 0x3d,
+      0x55, 0xb7, 0x6f, 0x7c, 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31,
+      0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, 0xa5, 0x9e, 0x12, 0xa7,
+      0x68, 0xa0, 0x7e, 0xdf, 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f,
+      0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, 0x82, 0xfe, 0x7e, 0x33,
+      0xb1, 0x78, 0x7f, 0x70, 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48,
+      0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, 0x86, 0xe5, 0xc9, 0x15,
+      0x88, 0x14, 0x53, 0xd8, 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41,
+      0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, 0xd5, 0xce, 0x8f, 0xfe,
+      0xbb, 0xc8, 0x5c, 0x30, 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89,
+      0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, 0xfd, 0x03, 0xd2, 0xdd,
+      0xe4, 0xf0, 0xb4, 0x20, 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde,
+      0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, 0xcf, 0xec, 0x8a, 0x59,
+      0x4a, 0x73, 0xca, 0xc5, 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4,
+      0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, 0xdb, 0xe5, 0x52, 0x38,
+      0xf9, 0x59, 0x91, 0x2d, 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42,
+      0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, 0x71, 0x10, 0x3a, 0xbd,
+      0x92, 0x8f, 0x9b, 0xa2, 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c,
+      0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, 0x45, 0x84, 0xb0};
 
-  const uint8 short_integer_without_high_bit[] = {
-    0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 
-    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 
-    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 
-    0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 
-    0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, 
-    0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, 
-    0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, 
-    0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, 
-    0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, 
-    0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, 
-    0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, 
-    0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, 
-    0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, 
-    0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, 
-    0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, 
-    0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, 
-    0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, 
-    0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, 
-    0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, 
-    0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, 
-    0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, 
-    0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, 
-    0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, 
-    0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, 
-    0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, 
-    0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, 
-    0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, 
-    0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, 
-    0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, 
-    0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, 
-    0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, 
-    0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, 
-    0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, 
-    0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, 
-    0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, 
-    0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, 
-    0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, 
-    0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, 
-    0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, 
-    0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, 
-    0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, 
-    0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, 
-    0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, 
-    0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, 
-    0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, 
-    0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, 
-    0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, 
-    0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, 
-    0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, 
-    0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, 
-    0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, 
-    0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, 
-    0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, 
-    0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, 
-    0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, 
-    0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, 
-    0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, 
-    0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, 
-    0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, 
-    0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, 
-    0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, 
-    0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, 
-    0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, 
-    0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, 
-    0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, 
-    0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, 
-    0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, 
-    0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, 
-    0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, 
-    0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, 
-    0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, 
-    0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, 
-    0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, 
-    0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, 
-    0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, 
-    0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, 
-    0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, 
-    0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, 
-    0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, 
-    0xea, 0xbe
-  };
+  const uint8_t short_integer_without_high_bit[] = {
+      0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+      0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+      0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+      0x00, 0xc3, 0x9e, 0x8d, 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03,
+      0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, 0x85, 0x27, 0x81, 0x52,
+      0xf2, 0x1b, 0x3e, 0x5b, 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5,
+      0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, 0x92, 0x7e, 0x34, 0xcf,
+      0x37, 0x82, 0x48, 0x2d, 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a,
+      0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, 0x01, 0x00, 0x1b, 0xfe,
+      0x06, 0x15, 0xc6, 0xe3, 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb,
+      0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, 0x53, 0x78, 0x06, 0x03,
+      0x0d, 0x59, 0xf5, 0x20, 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52,
+      0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, 0x02, 0x2d, 0x49, 0xd5,
+      0x15, 0x5b, 0xf1, 0xd9, 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01,
+      0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, 0x95, 0x17, 0x34, 0x88,
+      0xf6, 0x91, 0xc7, 0x3f, 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84,
+      0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, 0xc5, 0x21, 0x61, 0x10,
+      0xa8, 0x69, 0x09, 0x1e, 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b,
+      0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, 0x84, 0x3e, 0xb9, 0xe5,
+      0xe6, 0x31, 0x0a, 0x01, 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6,
+      0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, 0x7b, 0xd3, 0x97, 0x5a,
+      0x44, 0x3a, 0xee, 0xff, 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a,
+      0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, 0xb3, 0xa8, 0xb2, 0xc7,
+      0x73, 0x25, 0x0f, 0x58, 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe,
+      0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, 0xe0, 0x28, 0x15, 0x02,
+      0x41, 0x00, 0xeb, 0x15, 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22,
+      0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, 0xad, 0xf4, 0x57, 0x68,
+      0x90, 0xb7, 0x9f, 0xe2, 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b,
+      0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, 0x1d, 0xb8, 0x5c, 0x96,
+      0xeb, 0x04, 0x08, 0xe1, 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1,
+      0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, 0x00, 0xd5, 0x06, 0x45,
+      0xd7, 0x55, 0x63, 0x1a, 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39,
+      0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, 0xe2, 0x5b, 0xc6, 0xd2,
+      0x55, 0xdd, 0xab, 0x55, 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73,
+      0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, 0x1d, 0xce, 0x18, 0x7f,
+      0xb0, 0xc8, 0x47, 0x77, 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94,
+      0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, 0x17, 0x44, 0x75, 0x0a,
+      0xf1, 0x10, 0xee, 0x1b, 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15,
+      0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, 0xf7, 0x27, 0xe7, 0xe8,
+      0x2c, 0x47, 0xf1, 0x0f, 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19,
+      0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, 0x0b, 0x60, 0x7f, 0x94,
+      0x2a, 0x80, 0x8d, 0x22, 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2,
+      0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, 0x05, 0xc5, 0x3c, 0x9d,
+      0xcf, 0x8a, 0x60, 0xc7, 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3,
+      0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, 0x4a, 0xd2, 0x6a, 0xbc,
+      0x8b, 0x62, 0x22, 0x3c, 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e,
+      0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, 0xb7, 0x3e, 0x91, 0x9c,
+      0x09, 0xf6, 0xd7, 0x02, 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8,
+      0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, 0x91, 0x58, 0xff, 0xf9,
+      0x19, 0xac, 0x3a, 0x73, 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9,
+      0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, 0x43, 0x9b, 0x39, 0xc8,
+      0x04, 0x4d, 0x2b, 0x01, 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43,
+      0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, 0xea, 0xbe};
 
-  std::vector<uint8> input1;
-  std::vector<uint8> input2;
+  std::vector<uint8_t> input1;
+  std::vector<uint8_t> input2;
 
   input1.resize(sizeof(short_integer_with_high_bit));
   input2.resize(sizeof(short_integer_without_high_bit));
 
-  memcpy(&input1.front(), short_integer_with_high_bit,
-         sizeof(short_integer_with_high_bit));
-  memcpy(&input2.front(), short_integer_without_high_bit,
-         sizeof(short_integer_without_high_bit));
+  SbMemoryCopy(&input1.front(), short_integer_with_high_bit,
+               sizeof(short_integer_with_high_bit));
+  SbMemoryCopy(&input2.front(), short_integer_without_high_bit,
+               sizeof(short_integer_without_high_bit));
 
-  scoped_ptr<crypto::RSAPrivateKey> keypair1(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair1(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input1));
-  scoped_ptr<crypto::RSAPrivateKey> keypair2(
+  std::unique_ptr<crypto::RSAPrivateKey> keypair2(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input2));
   ASSERT_TRUE(keypair1.get());
   ASSERT_TRUE(keypair2.get());
 
-  std::vector<uint8> output1;
-  std::vector<uint8> output2;
+  std::vector<uint8_t> output1;
+  std::vector<uint8_t> output2;
   ASSERT_TRUE(keypair1->ExportPrivateKey(&output1));
   ASSERT_TRUE(keypair2->ExportPrivateKey(&output2));
 
   ASSERT_EQ(input1.size(), output1.size());
   ASSERT_EQ(input2.size(), output2.size());
-  ASSERT_TRUE(0 == memcmp(&output1.front(), &input1.front(),
-                          input1.size()));
-  ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(),
-                          input2.size()));
+  ASSERT_EQ(0,
+            SbMemoryCompare(&output1.front(), &input1.front(), input1.size()));
+  ASSERT_EQ(0,
+            SbMemoryCompare(&output2.front(), &input2.front(), input2.size()));
 }
+
+TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) {
+  std::unique_ptr<crypto::RSAPrivateKey> key_pair(
+      crypto::RSAPrivateKey::Create(512));
+  ASSERT_TRUE(key_pair.get());
+
+  std::unique_ptr<crypto::RSAPrivateKey> key_copy(
+      crypto::RSAPrivateKey::CreateFromKey(key_pair->key()));
+  ASSERT_TRUE(key_copy.get());
+
+  std::vector<uint8_t> privkey;
+  std::vector<uint8_t> pubkey;
+  ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey));
+  ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey));
+
+  std::vector<uint8_t> privkey_copy;
+  std::vector<uint8_t> pubkey_copy;
+  ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy));
+  ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy));
+
+  ASSERT_EQ(privkey, privkey_copy);
+  ASSERT_EQ(pubkey, pubkey_copy);
+}
+
diff --git a/src/crypto/rsa_private_key_win.cc b/src/crypto/rsa_private_key_win.cc
deleted file mode 100644
index f870f6a..0000000
--- a/src/crypto/rsa_private_key_win.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright (c) 2012 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/rsa_private_key.h"
-
-#include <list>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_util.h"
-
-#pragma comment(lib, "crypt32.lib")
-
-namespace crypto {
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-  if (!result->InitProvider())
-    return NULL;
-
-  DWORD flags = CRYPT_EXPORTABLE;
-
-  // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
-  flags |= (num_bits << 16);
-  if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags,
-                   result->key_.receive()))
-    return NULL;
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-  if (!result->InitProvider())
-    return NULL;
-
-  PrivateKeyInfoCodec pki(false);  // Little-Endian
-  if (!pki.Import(input))
-    return NULL;
-
-  size_t blob_size = sizeof(PUBLICKEYSTRUC) +
-                     sizeof(RSAPUBKEY) +
-                     pki.modulus()->size() +
-                     pki.prime1()->size() +
-                     pki.prime2()->size() +
-                     pki.exponent1()->size() +
-                     pki.exponent2()->size() +
-                     pki.coefficient()->size() +
-                     pki.private_exponent()->size();
-  scoped_array<BYTE> blob(new BYTE[blob_size]);
-
-  uint8* dest = blob.get();
-  PUBLICKEYSTRUC* public_key_struc = reinterpret_cast<PUBLICKEYSTRUC*>(dest);
-  public_key_struc->bType = PRIVATEKEYBLOB;
-  public_key_struc->bVersion = 0x02;
-  public_key_struc->reserved = 0;
-  public_key_struc->aiKeyAlg = CALG_RSA_SIGN;
-  dest += sizeof(PUBLICKEYSTRUC);
-
-  RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest);
-  rsa_pub_key->magic = 0x32415352;
-  rsa_pub_key->bitlen = pki.modulus()->size() * 8;
-  int public_exponent_int = 0;
-  for (size_t i = pki.public_exponent()->size(); i > 0; --i) {
-    public_exponent_int <<= 8;
-    public_exponent_int |= (*pki.public_exponent())[i - 1];
-  }
-  rsa_pub_key->pubexp = public_exponent_int;
-  dest += sizeof(RSAPUBKEY);
-
-  memcpy(dest, &pki.modulus()->front(), pki.modulus()->size());
-  dest += pki.modulus()->size();
-  memcpy(dest, &pki.prime1()->front(), pki.prime1()->size());
-  dest += pki.prime1()->size();
-  memcpy(dest, &pki.prime2()->front(), pki.prime2()->size());
-  dest += pki.prime2()->size();
-  memcpy(dest, &pki.exponent1()->front(), pki.exponent1()->size());
-  dest += pki.exponent1()->size();
-  memcpy(dest, &pki.exponent2()->front(), pki.exponent2()->size());
-  dest += pki.exponent2()->size();
-  memcpy(dest, &pki.coefficient()->front(), pki.coefficient()->size());
-  dest += pki.coefficient()->size();
-  memcpy(dest, &pki.private_exponent()->front(),
-         pki.private_exponent()->size());
-  dest += pki.private_exponent()->size();
-
-  if (dest != blob.get() + blob_size) {
-    NOTREACHED();
-    return NULL;
-  }
-  if (!CryptImportKey(result->provider_,
-                      reinterpret_cast<uint8*>(public_key_struc),
-                      static_cast<DWORD>(blob_size), 0, CRYPT_EXPORTABLE,
-                      result->key_.receive())) {
-    return NULL;
-  }
-
-  return result.release();
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
-    const std::vector<uint8>& input) {
-  NOTIMPLEMENTED();
-  return NULL;
-}
-
-RSAPrivateKey::RSAPrivateKey() : provider_(NULL), key_(NULL) {}
-
-RSAPrivateKey::~RSAPrivateKey() {}
-
-bool RSAPrivateKey::InitProvider() {
-  return FALSE != CryptAcquireContext(provider_.receive(), NULL, NULL,
-                                      PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
-}
-
-RSAPrivateKey* RSAPrivateKey::Copy() const {
-  scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey());
-  if (!CryptContextAddRef(provider_, NULL, 0)) {
-    NOTREACHED();
-    return NULL;
-  }
-  copy->provider_.reset(provider_.get());
-  if (!CryptDuplicateKey(key_.get(), NULL, 0, copy->key_.receive()))
-    return NULL;
-  return copy.release();
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
-  // Export the key
-  DWORD blob_length = 0;
-  if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, NULL, &blob_length)) {
-    NOTREACHED();
-    return false;
-  }
-
-  scoped_array<uint8> blob(new uint8[blob_length]);
-  if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, blob.get(), &blob_length)) {
-    NOTREACHED();
-    return false;
-  }
-
-  uint8* pos = blob.get();
-  PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos);
-  pos += sizeof(PUBLICKEYSTRUC);
-
-  RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos);
-  pos += sizeof(RSAPUBKEY);
-
-  int mod_size = rsa_pub_key->bitlen / 8;
-  int primes_size = rsa_pub_key->bitlen / 16;
-
-  PrivateKeyInfoCodec pki(false);  // Little-Endian
-
-  pki.modulus()->assign(pos, pos + mod_size);
-  pos += mod_size;
-
-  pki.prime1()->assign(pos, pos + primes_size);
-  pos += primes_size;
-  pki.prime2()->assign(pos, pos + primes_size);
-  pos += primes_size;
-
-  pki.exponent1()->assign(pos, pos + primes_size);
-  pos += primes_size;
-  pki.exponent2()->assign(pos, pos + primes_size);
-  pos += primes_size;
-
-  pki.coefficient()->assign(pos, pos + primes_size);
-  pos += primes_size;
-
-  pki.private_exponent()->assign(pos, pos + mod_size);
-  pos += mod_size;
-
-  pki.public_exponent()->assign(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp),
-      reinterpret_cast<uint8*>(&rsa_pub_key->pubexp) + 4);
-
-  CHECK_EQ(pos - blob_length, reinterpret_cast<BYTE*>(publickey_struct));
-
-  return pki.Export(output);
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
-  DWORD key_info_len;
-  if (!CryptExportPublicKeyInfo(
-      provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-      NULL, &key_info_len)) {
-    NOTREACHED();
-    return false;
-  }
-
-  scoped_array<uint8> key_info(new uint8[key_info_len]);
-  if (!CryptExportPublicKeyInfo(
-      provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), &key_info_len)) {
-    NOTREACHED();
-    return false;
-  }
-
-  DWORD encoded_length;
-  if (!CryptEncodeObject(
-      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
-      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), NULL,
-      &encoded_length)) {
-    NOTREACHED();
-    return false;
-  }
-
-  scoped_array<BYTE> encoded(new BYTE[encoded_length]);
-  if (!CryptEncodeObject(
-      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
-      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), encoded.get(),
-      &encoded_length)) {
-    NOTREACHED();
-    return false;
-  }
-
-  output->assign(encoded.get(), encoded.get() + encoded_length);
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/run_all_unittests.cc b/src/crypto/run_all_unittests.cc
deleted file mode 100644
index 585601f..0000000
--- a/src/crypto/run_all_unittests.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 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 "base/test/main_hook.h"
-#include "base/test/test_suite.h"
-#include "crypto/nss_util.h"
-#include "starboard/client_porting/wrap_main/wrap_main.h"
-
-int TestSuiteRun(int argc, char** argv) {
-  MainHook hook(NULL, argc, argv);
-#if defined(USE_NSS)
-  // This is most likely not needed, but it basically replaces a similar call
-  // that was performed on test_support_base.
-  // TODO(rvargas) Bug 79359: remove this.
-  crypto::EnsureNSSInit();
-#endif  // defined(USE_NSS)
-  return base::TestSuite(argc, argv).Run();
-}
-
-STARBOARD_WRAP_SIMPLE_MAIN(TestSuiteRun);
diff --git a/src/crypto/scoped_capi_types.h b/src/crypto/scoped_capi_types.h
index 16a5192..97c7da8 100644
--- a/src/crypto/scoped_capi_types.h
+++ b/src/crypto/scoped_capi_types.h
@@ -6,11 +6,13 @@
 #define CRYPTO_SCOPED_CAPI_TYPES_H_
 
 #include <windows.h>
-#include <wincrypt.h>
 
 #include <algorithm>
 
 #include "base/logging.h"
+#include "base/macros.h"
+#include "crypto/wincrypt_shim.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -42,8 +44,8 @@
 
 // scoped_ptr-like class for the CryptoAPI cryptography and certificate
 // handles. Because these handles are defined as integer types, and not
-// pointers, the existing scoped classes, such as scoped_ptr_malloc, are
-// insufficient. The semantics are the same as scoped_ptr.
+// pointers, the existing scoped classes, such as scoped_ptr, are insufficient.
+// The semantics are the same as scoped_ptr.
 template <class CAPIHandle, typename FreeProc>
 class ScopedCAPIHandle {
  public:
diff --git a/src/crypto/scoped_nss_types.h b/src/crypto/scoped_nss_types.h
index da90fea..775330c 100644
--- a/src/crypto/scoped_nss_types.h
+++ b/src/crypto/scoped_nss_types.h
@@ -10,53 +10,55 @@
 #include <pk11pub.h>
 #include <plarena.h>
 
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
+#include "starboard/types.h"
 
 namespace crypto {
 
 template <typename Type, void (*Destroyer)(Type*)>
 struct NSSDestroyer {
   void operator()(Type* ptr) const {
-    if (ptr)
-      Destroyer(ptr);
+    Destroyer(ptr);
   }
 };
 
 template <typename Type, void (*Destroyer)(Type*, PRBool), PRBool freeit>
 struct NSSDestroyer1 {
   void operator()(Type* ptr) const {
-    if (ptr)
-      Destroyer(ptr, freeit);
+    Destroyer(ptr, freeit);
   }
 };
 
 // Define some convenient scopers around NSS pointers.
-typedef scoped_ptr_malloc<
-    PK11Context, NSSDestroyer1<PK11Context,
-                               PK11_DestroyContext,
-                               PR_TRUE> > ScopedPK11Context;
-typedef scoped_ptr_malloc<
-    PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot> > ScopedPK11Slot;
-typedef scoped_ptr_malloc<
-    PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey> > ScopedPK11SymKey;
-typedef scoped_ptr_malloc<
-    SECKEYPublicKey, NSSDestroyer<SECKEYPublicKey, SECKEY_DestroyPublicKey> >
+typedef std::unique_ptr<
+    PK11Context,
+    NSSDestroyer1<PK11Context, PK11_DestroyContext, PR_TRUE>>
+    ScopedPK11Context;
+typedef std::unique_ptr<PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot>>
+    ScopedPK11Slot;
+typedef std::unique_ptr<PK11SlotList,
+                        NSSDestroyer<PK11SlotList, PK11_FreeSlotList>>
+    ScopedPK11SlotList;
+typedef std::unique_ptr<PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey>>
+    ScopedPK11SymKey;
+typedef std::unique_ptr<SECKEYPublicKey,
+                        NSSDestroyer<SECKEYPublicKey, SECKEY_DestroyPublicKey>>
     ScopedSECKEYPublicKey;
-typedef scoped_ptr_malloc<
-    SECKEYPrivateKey, NSSDestroyer<SECKEYPrivateKey, SECKEY_DestroyPrivateKey> >
+typedef std::unique_ptr<
+    SECKEYPrivateKey,
+    NSSDestroyer<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>>
     ScopedSECKEYPrivateKey;
-typedef scoped_ptr_malloc<
-    SECAlgorithmID, NSSDestroyer1<SECAlgorithmID,
-                                  SECOID_DestroyAlgorithmID,
-                                  PR_TRUE> > ScopedSECAlgorithmID;
-typedef scoped_ptr_malloc<
-    SECItem, NSSDestroyer1<SECItem,
-                           SECITEM_FreeItem,
-                           PR_TRUE> > ScopedSECItem;
-typedef scoped_ptr_malloc<
-    PLArenaPool, NSSDestroyer1<PLArenaPool,
-                               PORT_FreeArena,
-                               PR_FALSE> > ScopedPLArenaPool;
+typedef std::unique_ptr<
+    SECAlgorithmID,
+    NSSDestroyer1<SECAlgorithmID, SECOID_DestroyAlgorithmID, PR_TRUE>>
+    ScopedSECAlgorithmID;
+typedef std::unique_ptr<SECItem,
+                        NSSDestroyer1<SECItem, SECITEM_FreeItem, PR_TRUE>>
+    ScopedSECItem;
+typedef std::unique_ptr<PLArenaPool,
+                        NSSDestroyer1<PLArenaPool, PORT_FreeArena, PR_FALSE>>
+    ScopedPLArenaPool;
 
 }  // namespace crypto
 
diff --git a/src/crypto/scoped_test_nss_chromeos_user.cc b/src/crypto/scoped_test_nss_chromeos_user.cc
new file mode 100644
index 0000000..49b92d4
--- /dev/null
+++ b/src/crypto/scoped_test_nss_chromeos_user.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 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/scoped_test_nss_chromeos_user.h"
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+
+namespace crypto {
+
+ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
+    const std::string& username_hash)
+    : username_hash_(username_hash), constructed_successfully_(false) {
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+  // This opens a software DB in the given folder. In production code that is in
+  // the home folder, but for testing the temp folder is used.
+  constructed_successfully_ =
+      InitializeNSSForChromeOSUser(username_hash, temp_dir_.GetPath());
+}
+
+ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
+  if (constructed_successfully_)
+    CloseChromeOSUserForTesting(username_hash_);
+}
+
+void ScopedTestNSSChromeOSUser::FinishInit() {
+  DCHECK(constructed_successfully_);
+  if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
+    return;
+  WillInitializeTPMForChromeOSUser(username_hash_);
+  InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
+}
+
+}  // namespace crypto
diff --git a/src/crypto/scoped_test_nss_chromeos_user.h b/src/crypto/scoped_test_nss_chromeos_user.h
new file mode 100644
index 0000000..9202b0f
--- /dev/null
+++ b/src/crypto/scoped_test_nss_chromeos_user.h
@@ -0,0 +1,43 @@
+// Copyright 2014 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_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Opens a persistent NSS software database in a temporary directory for the
+// user with |username_hash|. This database will be used for both the user's
+// public and private slot.
+class CRYPTO_EXPORT ScopedTestNSSChromeOSUser {
+ public:
+  // Opens the software database and sets the public slot for the user. The
+  // private slot will not be initialized until FinishInit() is called.
+  explicit ScopedTestNSSChromeOSUser(const std::string& username_hash);
+  ~ScopedTestNSSChromeOSUser();
+
+  std::string username_hash() const { return username_hash_; }
+  bool constructed_successfully() const { return constructed_successfully_; }
+
+  // Completes initialization of user. Causes any waiting private slot callbacks
+  // to run, see GetPrivateSlotForChromeOSUser().
+  void FinishInit();
+
+ private:
+  const std::string username_hash_;
+  base::ScopedTempDir temp_dir_;
+  bool constructed_successfully_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
diff --git a/src/crypto/scoped_test_nss_db.cc b/src/crypto/scoped_test_nss_db.cc
new file mode 100644
index 0000000..ea953a7
--- /dev/null
+++ b/src/crypto/scoped_test_nss_db.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 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/scoped_test_nss_db.h"
+
+#include <cert.h>
+
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+#include "starboard/types.h"
+
+namespace crypto {
+
+ScopedTestNSSDB::ScopedTestNSSDB() {
+  EnsureNSSInit();
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+
+  const char kTestDescription[] = "Test DB";
+  slot_ = OpenSoftwareNSSDB(temp_dir_.GetPath(), kTestDescription);
+}
+
+ScopedTestNSSDB::~ScopedTestNSSDB() {
+  // Remove trust from any certs in the test DB before closing it. Otherwise NSS
+  // may cache verification results even after the test DB is gone.
+  if (slot_) {
+    CERTCertList* cert_list = PK11_ListCertsInSlot(slot_.get());
+    for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
+         !CERT_LIST_END(node, cert_list);
+         node = CERT_LIST_NEXT(node)) {
+      CERTCertTrust trust = {0};
+      if (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), node->cert, &trust) !=
+          SECSuccess) {
+        LOG(ERROR) << "CERT_ChangeCertTrust failed: " << PORT_GetError();
+      }
+    }
+    CERT_DestroyCertList(cert_list);
+  }
+
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  if (slot_) {
+    SECStatus status = SECMOD_CloseUserDB(slot_.get());
+    if (status != SECSuccess)
+      PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+  }
+
+  if (!temp_dir_.Delete())
+    LOG(ERROR) << "Could not delete temporary directory.";
+}
+
+}  // namespace crypto
diff --git a/src/crypto/scoped_test_nss_db.h b/src/crypto/scoped_test_nss_db.h
new file mode 100644
index 0000000..c01653f
--- /dev/null
+++ b/src/crypto/scoped_test_nss_db.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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_SCOPED_TEST_NSS_DB_H_
+#define CRYPTO_SCOPED_TEST_NSS_DB_H_
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+// Opens a persistent NSS database in a temporary directory.
+// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB
+// will not be closed automatically.
+class CRYPTO_EXPORT ScopedTestNSSDB {
+ public:
+  ScopedTestNSSDB();
+  ~ScopedTestNSSDB();
+
+  bool is_open() const { return !!slot_; }
+  PK11SlotInfo* slot() const { return slot_.get(); }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+  ScopedPK11Slot slot_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_DB_H_
diff --git a/src/crypto/scoped_test_system_nss_key_slot.cc b/src/crypto/scoped_test_system_nss_key_slot.cc
new file mode 100644
index 0000000..53fbbff
--- /dev/null
+++ b/src/crypto/scoped_test_system_nss_key_slot.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 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/scoped_test_system_nss_key_slot.h"
+
+#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_db.h"
+
+namespace crypto {
+
+ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot()
+    : test_db_(new ScopedTestNSSDB) {
+  if (!test_db_->is_open())
+    return;
+  SetSystemKeySlotForTesting(
+      ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot())));
+}
+
+ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() {
+  SetSystemKeySlotForTesting(ScopedPK11Slot());
+}
+
+bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const {
+  return test_db_->is_open();
+}
+
+PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const {
+  return test_db_->slot();
+}
+
+}  // namespace crypto
diff --git a/src/crypto/scoped_test_system_nss_key_slot.h b/src/crypto/scoped_test_system_nss_key_slot.h
new file mode 100644
index 0000000..ae9b2cd
--- /dev/null
+++ b/src/crypto/scoped_test_system_nss_key_slot.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+
+// Forward declaration, from <pk11pub.h>
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+
+namespace crypto {
+
+class ScopedTestNSSDB;
+
+// Opens a persistent NSS software database in a temporary directory and sets
+// the test system slot to the opened database. This helper should be created in
+// tests to fake the system token that is usually provided by the Chaps module.
+// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will
+// return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if this helper is used.
+// At most one instance of this helper must be used at a time.
+class CRYPTO_EXPORT ScopedTestSystemNSSKeySlot {
+ public:
+  ScopedTestSystemNSSKeySlot();
+  ~ScopedTestSystemNSSKeySlot();
+
+  bool ConstructedSuccessfully() const;
+  PK11SlotInfo* slot() const;
+
+ private:
+  std::unique_ptr<ScopedTestNSSDB> test_db_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestSystemNSSKeySlot);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
diff --git a/src/crypto/secure_hash.cc b/src/crypto/secure_hash.cc
new file mode 100644
index 0000000..18d058a
--- /dev/null
+++ b/src/crypto/secure_hash.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 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/secure_hash.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/pickle.h"
+#include "crypto/openssl_util.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
+
+namespace crypto {
+
+namespace {
+
+class SecureHashSHA256 : public SecureHash {
+ public:
+  SecureHashSHA256() {
+    SHA256_Init(&ctx_);
+  }
+
+  SecureHashSHA256(const SecureHashSHA256& other) {
+    SbMemoryCopy(&ctx_, &other.ctx_, sizeof(ctx_));
+  }
+
+  ~SecureHashSHA256() override {
+    OPENSSL_cleanse(&ctx_, sizeof(ctx_));
+  }
+
+  void Update(const void* input, size_t len) override {
+    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
+  }
+
+  void Finish(void* output, size_t len) override {
+    ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result(
+        static_cast<unsigned char*>(output), len);
+    SHA256_Final(result.safe_buffer(), &ctx_);
+  }
+
+  std::unique_ptr<SecureHash> Clone() const override {
+    return std::make_unique<SecureHashSHA256>(*this);
+  }
+
+  size_t GetHashLength() const override { return SHA256_DIGEST_LENGTH; }
+
+ private:
+  SHA256_CTX ctx_;
+};
+
+}  // namespace
+
+std::unique_ptr<SecureHash> SecureHash::Create(Algorithm algorithm) {
+  switch (algorithm) {
+    case SHA256:
+      return std::make_unique<SecureHashSHA256>();
+    default:
+      NOTIMPLEMENTED();
+      return nullptr;
+  }
+}
+
+}  // namespace crypto
diff --git a/src/crypto/secure_hash.h b/src/crypto/secure_hash.h
index 173fd0a..7e89211 100644
--- a/src/crypto/secure_hash.h
+++ b/src/crypto/secure_hash.h
@@ -5,16 +5,17 @@
 #ifndef CRYPTO_SECURE_HASH_H_
 #define CRYPTO_SECURE_HASH_H_
 
-#include "base/basictypes.h"
-#include "crypto/crypto_export.h"
+#include <memory>
 
-class Pickle;
-class PickleIterator;
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
 // A wrapper to calculate secure hashes incrementally, allowing to
-// be used when the full input is not known in advance.
+// be used when the full input is not known in advance. The end result will the
+// same as if we have the full input in advance.
 class CRYPTO_EXPORT SecureHash {
  public:
   enum Algorithm {
@@ -22,21 +23,16 @@
   };
   virtual ~SecureHash() {}
 
-  static SecureHash* Create(Algorithm type);
+  static std::unique_ptr<SecureHash> Create(Algorithm type);
 
   virtual void Update(const void* input, size_t len) = 0;
   virtual void Finish(void* output, size_t len) = 0;
+  virtual size_t GetHashLength() const = 0;
 
-  // Serialize the context, so it can be restored at a later time.
-  // |pickle| will contain the serialized data.
-  // Returns whether or not |pickle| was filled.
-  virtual bool Serialize(Pickle* pickle) = 0;
-
-  // Restore the context that was saved earlier.
-  // |data_iterator| allows this to be used as part of a larger pickle.
-  // |pickle| holds the saved data.
-  // Returns success or failure.
-  virtual bool Deserialize(PickleIterator* data_iterator) = 0;
+  // Create a clone of this SecureHash. The returned clone and this both
+  // represent the same hash state. But from this point on, calling
+  // Update()/Finish() on either doesn't affect the state of the other.
+  virtual std::unique_ptr<SecureHash> Clone() const = 0;
 
  protected:
   SecureHash() {}
diff --git a/src/crypto/secure_hash_openssl.cc b/src/crypto/secure_hash_openssl.cc
deleted file mode 100644
index 743057b..0000000
--- a/src/crypto/secure_hash_openssl.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2012 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/secure_hash.h"
-
-#include <openssl/crypto.h>
-#include <openssl/sha.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/pickle.h"
-#include "crypto/openssl_util.h"
-
-namespace crypto {
-
-namespace {
-
-const char kSHA256Descriptor[] = "OpenSSL";
-
-class SecureHashSHA256OpenSSL : public SecureHash {
- public:
-  static const int kSecureHashVersion = 1;
-
-  SecureHashSHA256OpenSSL() {
-    SHA256_Init(&ctx_);
-  }
-
-  virtual ~SecureHashSHA256OpenSSL() {
-    OPENSSL_cleanse(&ctx_, sizeof(ctx_));
-  }
-
-  virtual void Update(const void* input, size_t len) {
-    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
-  }
-
-  virtual void Finish(void* output, size_t len) {
-    ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result(
-        static_cast<unsigned char*>(output), len);
-    SHA256_Final(result.safe_buffer(), &ctx_);
-  }
-
-  virtual bool Serialize(Pickle* pickle);
-  virtual bool Deserialize(PickleIterator* data_iterator);
-
- private:
-  SHA256_CTX ctx_;
-};
-
-bool SecureHashSHA256OpenSSL::Serialize(Pickle* pickle) {
-  if (!pickle)
-    return false;
-
-  if (!pickle->WriteInt(kSecureHashVersion) ||
-      !pickle->WriteString(kSHA256Descriptor) ||
-      !pickle->WriteBytes(&ctx_, sizeof(ctx_))) {
-    return false;
-  }
-
-  return true;
-}
-
-bool SecureHashSHA256OpenSSL::Deserialize(PickleIterator* data_iterator) {
-  if (!data_iterator)
-    return false;
-
-  int version;
-  if (!data_iterator->ReadInt(&version))
-    return false;
-
-  if (version > kSecureHashVersion)
-    return false;  // We don't know how to deal with this.
-
-  std::string type;
-  if (!data_iterator->ReadString(&type))
-    return false;
-
-  if (type != kSHA256Descriptor)
-    return false;  // It's the wrong kind.
-
-  const char* data = NULL;
-  if (!data_iterator->ReadBytes(&data, sizeof(ctx_)))
-    return false;
-
-  memcpy(&ctx_, data, sizeof(ctx_));
-
-  return true;
-}
-
-}  // namespace
-
-SecureHash* SecureHash::Create(Algorithm algorithm) {
-  switch (algorithm) {
-    case SHA256:
-      return new SecureHashSHA256OpenSSL();
-    default:
-      NOTIMPLEMENTED();
-      return NULL;
-  }
-}
-
-}  // namespace crypto
diff --git a/src/crypto/secure_hash_unittest.cc b/src/crypto/secure_hash_unittest.cc
index 42b9ade..cf37b9c 100644
--- a/src/crypto/secure_hash_unittest.cc
+++ b/src/crypto/secure_hash_unittest.cc
@@ -4,70 +4,104 @@
 
 #include "crypto/secure_hash.h"
 
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/pickle.h"
+#include <memory>
+#include <string>
+
 #include "crypto/sha2.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(SecureHashTest, TestUpdate) {
   // Example B.3 from FIPS 180-2: long message.
   std::string input3(500000, 'a');  // 'a' repeated half a million times
-  int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c,
-                      0x99, 0x14, 0xfb, 0x92,
-                      0x81, 0xa1, 0xc7, 0xe2,
-                      0x84, 0xd7, 0x3e, 0x67,
-                      0xf1, 0x80, 0x9a, 0x48,
-                      0xa4, 0x97, 0x20, 0x0e,
-                      0x04, 0x6d, 0x39, 0xcc,
-                      0xc7, 0x11, 0x2c, 0xd0 };
+  const int kExpectedHashOfInput3[] = {
+      0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
+      0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
+      0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0};
 
-  uint8 output3[crypto::kSHA256Length];
+  uint8_t output3[crypto::kSHA256Length];
 
-  scoped_ptr<crypto::SecureHash> ctx(crypto::SecureHash::Create(
-      crypto::SecureHash::SHA256));
+  std::unique_ptr<crypto::SecureHash> ctx(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
   ctx->Update(input3.data(), input3.size());
   ctx->Update(input3.data(), input3.size());
 
   ctx->Finish(output3, sizeof(output3));
   for (size_t i = 0; i < crypto::kSHA256Length; i++)
-    EXPECT_EQ(expected3[i], static_cast<int>(output3[i]));
+    EXPECT_EQ(kExpectedHashOfInput3[i], static_cast<int>(output3[i]));
 }
 
-// Save the crypto state mid-stream, and create another instance with the
-// saved state.  Then feed the same data afterwards to both.
-// When done, both should have the same hash value.
-TEST(SecureHashTest, TestSerialization) {
+TEST(SecureHashTest, TestClone) {
   std::string input1(10001, 'a');  // 'a' repeated 10001 times
-  std::string input2(10001, 'b');  // 'b' repeated 10001 times
-  std::string input3(10001, 'c');  // 'c' repeated 10001 times
-  std::string input4(10001, 'd');  // 'd' repeated 10001 times
-  std::string input5(10001, 'e');  // 'e' repeated 10001 times
+  std::string input2(10001, 'd');  // 'd' repeated 10001 times
 
-  uint8 output1[crypto::kSHA256Length];
-  uint8 output2[crypto::kSHA256Length];
+  const uint8_t kExpectedHashOfInput1[crypto::kSHA256Length] = {
+      0x0c, 0xab, 0x99, 0xa0, 0x58, 0x60, 0x0f, 0xfa, 0xad, 0x12, 0x92,
+      0xd0, 0xc5, 0x3c, 0x05, 0x48, 0xeb, 0xaf, 0x88, 0xdd, 0x1d, 0x01,
+      0x03, 0x03, 0x45, 0x70, 0x5f, 0x01, 0x8a, 0x81, 0x39, 0x09};
+  const uint8_t kExpectedHashOfInput1And2[crypto::kSHA256Length] = {
+      0x4c, 0x8e, 0x26, 0x5a, 0xc3, 0x85, 0x1f, 0x1f, 0xa5, 0x04, 0x1c,
+      0xc7, 0x88, 0x53, 0x1c, 0xc7, 0x80, 0x47, 0x15, 0xfb, 0x47, 0xff,
+      0x72, 0xb1, 0x28, 0x37, 0xb0, 0x4d, 0x6e, 0x22, 0x2e, 0x4d};
 
-  scoped_ptr<crypto::SecureHash> ctx1(crypto::SecureHash::Create(
-      crypto::SecureHash::SHA256));
-  scoped_ptr<crypto::SecureHash> ctx2(crypto::SecureHash::Create(
-      crypto::SecureHash::SHA256));
-  Pickle pickle;
+  uint8_t output1[crypto::kSHA256Length];
+  uint8_t output2[crypto::kSHA256Length];
+  uint8_t output3[crypto::kSHA256Length];
+
+  std::unique_ptr<crypto::SecureHash> ctx1(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
   ctx1->Update(input1.data(), input1.size());
+
+  std::unique_ptr<crypto::SecureHash> ctx2(ctx1->Clone());
+  std::unique_ptr<crypto::SecureHash> ctx3(ctx2->Clone());
+  // At this point, ctx1, ctx2, and ctx3 are all equivalent and represent the
+  // state after hashing input1.
+
+  // Updating ctx1 and ctx2 with input2 should produce equivalent results.
   ctx1->Update(input2.data(), input2.size());
-  ctx1->Update(input3.data(), input3.size());
-
-  EXPECT_TRUE(ctx1->Serialize(&pickle));
-  ctx1->Update(input4.data(), input4.size());
-  ctx1->Update(input5.data(), input5.size());
-
   ctx1->Finish(output1, sizeof(output1));
 
-  PickleIterator data_iterator(pickle);
-  EXPECT_TRUE(ctx2->Deserialize(&data_iterator));
-  ctx2->Update(input4.data(), input4.size());
-  ctx2->Update(input5.data(), input5.size());
-
+  ctx2->Update(input2.data(), input2.size());
   ctx2->Finish(output2, sizeof(output2));
 
-  EXPECT_EQ(0, memcmp(output1, output2, crypto::kSHA256Length));
+  EXPECT_EQ(0, SbMemoryCompare(output1, output2, crypto::kSHA256Length));
+  EXPECT_EQ(0, SbMemoryCompare(output1, kExpectedHashOfInput1And2,
+                               crypto::kSHA256Length));
+
+  // Finish() ctx3, which should produce the hash of input1.
+  ctx3->Finish(&output3, sizeof(output3));
+  EXPECT_EQ(0, SbMemoryCompare(output3, kExpectedHashOfInput1,
+                               crypto::kSHA256Length));
+}
+
+TEST(SecureHashTest, TestLength) {
+  std::unique_ptr<crypto::SecureHash> ctx(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  EXPECT_EQ(crypto::kSHA256Length, ctx->GetHashLength());
+}
+
+TEST(SecureHashTest, Equality) {
+  std::string input1(10001, 'a');  // 'a' repeated 10001 times
+  std::string input2(10001, 'd');  // 'd' repeated 10001 times
+
+  uint8_t output1[crypto::kSHA256Length];
+  uint8_t output2[crypto::kSHA256Length];
+
+  // Call Update() twice on input1 and input2.
+  std::unique_ptr<crypto::SecureHash> ctx1(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  ctx1->Update(input1.data(), input1.size());
+  ctx1->Update(input2.data(), input2.size());
+  ctx1->Finish(output1, sizeof(output1));
+
+  // Call Update() once one input1 + input2 (concatenation).
+  std::unique_ptr<crypto::SecureHash> ctx2(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  std::string input3 = input1 + input2;
+  ctx2->Update(input3.data(), input3.size());
+  ctx2->Finish(output2, sizeof(output2));
+
+  // The hash should be the same.
+  EXPECT_EQ(0, SbMemoryCompare(output1, output2, crypto::kSHA256Length));
 }
diff --git a/src/crypto/secure_util.cc b/src/crypto/secure_util.cc
index 3fe8aa9..ac261ab 100644
--- a/src/crypto/secure_util.cc
+++ b/src/crypto/secure_util.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "crypto/secure_util.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
diff --git a/src/crypto/secure_util.h b/src/crypto/secure_util.h
index cfe05ca..1523cc6 100644
--- a/src/crypto/secure_util.h
+++ b/src/crypto/secure_util.h
@@ -5,9 +5,8 @@
 #ifndef CRYPTO_SECURE_UTIL_H_
 #define CRYPTO_SECURE_UTIL_H_
 
-#include <stddef.h>
-
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
diff --git a/src/crypto/sha2.cc b/src/crypto/sha2.cc
index 6f36237..7c350bf 100644
--- a/src/crypto/sha2.cc
+++ b/src/crypto/sha2.cc
@@ -4,21 +4,23 @@
 
 #include "crypto/sha2.h"
 
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
 #include "base/stl_util.h"
 #include "crypto/secure_hash.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
-void SHA256HashString(const base::StringPiece& str, void* output, size_t len) {
-  scoped_ptr<SecureHash> ctx(SecureHash::Create(SecureHash::SHA256));
+void SHA256HashString(base::StringPiece str, void* output, size_t len) {
+  std::unique_ptr<SecureHash> ctx(SecureHash::Create(SecureHash::SHA256));
   ctx->Update(str.data(), str.length());
   ctx->Finish(output, len);
 }
 
-std::string SHA256HashString(const base::StringPiece& str) {
+std::string SHA256HashString(base::StringPiece str) {
   std::string output(kSHA256Length, 0);
-  SHA256HashString(str, string_as_array(&output), output.size());
+  SHA256HashString(str, base::data(output), output.size());
   return output;
 }
 
diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h
index e235f82..6d8f5a3 100644
--- a/src/crypto/sha2.h
+++ b/src/crypto/sha2.h
@@ -7,8 +7,9 @@
 
 #include <string>
 
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -21,12 +22,13 @@
 // Computes the SHA-256 hash of the input string 'str' and stores the first
 // 'len' bytes of the hash in the output buffer 'output'.  If 'len' > 32,
 // only 32 bytes (the full hash) are stored in the 'output' buffer.
-CRYPTO_EXPORT void SHA256HashString(const base::StringPiece& str,
-                                    void* output, size_t len);
+CRYPTO_EXPORT void SHA256HashString(base::StringPiece str,
+                                    void* output,
+                                    size_t len);
 
 // Convenience version of the above that returns the result in a 32-byte
 // string.
-CRYPTO_EXPORT std::string SHA256HashString(const base::StringPiece& str);
+CRYPTO_EXPORT std::string SHA256HashString(base::StringPiece str);
 
 }  // namespace crypto
 
diff --git a/src/crypto/sha2_unittest.cc b/src/crypto/sha2_unittest.cc
index 78da136..72095e4 100644
--- a/src/crypto/sha2_unittest.cc
+++ b/src/crypto/sha2_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "crypto/sha2.h"
 
-#include "base/basictypes.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(Sha256Test, Test1) {
@@ -19,12 +19,12 @@
                       0xb4, 0x10, 0xff, 0x61,
                       0xf2, 0x00, 0x15, 0xad };
 
-  uint8 output1[crypto::kSHA256Length];
+  uint8_t output1[crypto::kSHA256Length];
   crypto::SHA256HashString(input1, output1, sizeof(output1));
   for (size_t i = 0; i < crypto::kSHA256Length; i++)
     EXPECT_EQ(expected1[i], static_cast<int>(output1[i]));
 
-  uint8 output_truncated1[4];  // 4 bytes == 32 bits
+  uint8_t output_truncated1[4];  // 4 bytes == 32 bits
   crypto::SHA256HashString(input1,
                            output_truncated1, sizeof(output_truncated1));
   for (size_t i = 0; i < sizeof(output_truncated1); i++)
@@ -47,7 +47,7 @@
   std::string output1 = crypto::SHA256HashString(input1);
   ASSERT_EQ(crypto::kSHA256Length, output1.size());
   for (size_t i = 0; i < crypto::kSHA256Length; i++)
-    EXPECT_EQ(expected1[i], static_cast<uint8>(output1[i]));
+    EXPECT_EQ(expected1[i], static_cast<uint8_t>(output1[i]));
 }
 
 TEST(Sha256Test, Test2) {
@@ -63,12 +63,12 @@
                       0xf6, 0xec, 0xed, 0xd4,
                       0x19, 0xdb, 0x06, 0xc1 };
 
-  uint8 output2[crypto::kSHA256Length];
+  uint8_t output2[crypto::kSHA256Length];
   crypto::SHA256HashString(input2, output2, sizeof(output2));
   for (size_t i = 0; i < crypto::kSHA256Length; i++)
     EXPECT_EQ(expected2[i], static_cast<int>(output2[i]));
 
-  uint8 output_truncated2[6];
+  uint8_t output_truncated2[6];
   crypto::SHA256HashString(input2,
                            output_truncated2, sizeof(output_truncated2));
   for (size_t i = 0; i < sizeof(output_truncated2); i++)
@@ -87,12 +87,12 @@
                       0x04, 0x6d, 0x39, 0xcc,
                       0xc7, 0x11, 0x2c, 0xd0 };
 
-  uint8 output3[crypto::kSHA256Length];
+  uint8_t output3[crypto::kSHA256Length];
   crypto::SHA256HashString(input3, output3, sizeof(output3));
   for (size_t i = 0; i < crypto::kSHA256Length; i++)
     EXPECT_EQ(expected3[i], static_cast<int>(output3[i]));
 
-  uint8 output_truncated3[12];
+  uint8_t output_truncated3[12];
   crypto::SHA256HashString(input3,
                            output_truncated3, sizeof(output_truncated3));
   for (size_t i = 0; i < sizeof(output_truncated3); i++)
diff --git a/src/crypto/signature_creator.cc b/src/crypto/signature_creator.cc
new file mode 100644
index 0000000..5bab09a
--- /dev/null
+++ b/src/crypto/signature_creator.cc
@@ -0,0 +1,110 @@
+// Copyright (c) 2012 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/signature_creator.h"
+
+#include "base/logging.h"
+#include "crypto/openssl_util.h"
+#include "crypto/rsa_private_key.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+
+namespace crypto {
+
+namespace {
+
+const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) {
+  switch (hash_alg) {
+    case SignatureCreator::SHA1:
+      return EVP_sha1();
+    case SignatureCreator::SHA256:
+      return EVP_sha256();
+  }
+  return nullptr;
+}
+
+int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) {
+  switch (hash_alg) {
+    case SignatureCreator::SHA1:
+      return NID_sha1;
+    case SignatureCreator::SHA256:
+      return NID_sha256;
+  }
+  return NID_undef;
+}
+
+}  // namespace
+
+SignatureCreator::~SignatureCreator() {
+  EVP_MD_CTX_destroy(sign_context_);
+}
+
+// static
+std::unique_ptr<SignatureCreator> SignatureCreator::Create(
+    RSAPrivateKey* key,
+    HashAlgorithm hash_alg) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SignatureCreator> result(new SignatureCreator);
+  const EVP_MD* const digest = ToOpenSSLDigest(hash_alg);
+  DCHECK(digest);
+  if (!digest) {
+    return nullptr;
+  }
+  if (!EVP_DigestSignInit(result->sign_context_, nullptr, digest, nullptr,
+                          key->key())) {
+    return nullptr;
+  }
+  return result;
+}
+
+// static
+bool SignatureCreator::Sign(RSAPrivateKey* key,
+                            HashAlgorithm hash_alg,
+                            const uint8_t* data,
+                            int data_len,
+                            std::vector<uint8_t>* signature) {
+  bssl::UniquePtr<RSA> rsa_key(EVP_PKEY_get1_RSA(key->key()));
+  if (!rsa_key)
+    return false;
+  signature->resize(RSA_size(rsa_key.get()));
+
+  unsigned int len = 0;
+  if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len,
+                signature->data(), &len, rsa_key.get())) {
+    signature->clear();
+    return false;
+  }
+  signature->resize(len);
+  return true;
+}
+
+bool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  return !!EVP_DigestSignUpdate(sign_context_, data_part, data_part_len);
+}
+
+bool SignatureCreator::Final(std::vector<uint8_t>* signature) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  // Determine the maximum length of the signature.
+  size_t len = 0;
+  if (!EVP_DigestSignFinal(sign_context_, nullptr, &len)) {
+    signature->clear();
+    return false;
+  }
+  signature->resize(len);
+
+  // Sign it.
+  if (!EVP_DigestSignFinal(sign_context_, signature->data(), &len)) {
+    signature->clear();
+    return false;
+  }
+  signature->resize(len);
+  return true;
+}
+
+SignatureCreator::SignatureCreator() : sign_context_(EVP_MD_CTX_create()) {}
+
+}  // namespace crypto
diff --git a/src/crypto/signature_creator.h b/src/crypto/signature_creator.h
index 301ab19..f4a43b4 100644
--- a/src/crypto/signature_creator.h
+++ b/src/crypto/signature_creator.h
@@ -5,62 +5,58 @@
 #ifndef CRYPTO_SIGNATURE_CREATOR_H_
 #define CRYPTO_SIGNATURE_CREATOR_H_
 
-#include "build/build_config.h"
-
-#if defined(USE_OPENSSL)
-// Forward declaration for openssl/*.h
-typedef struct env_md_ctx_st EVP_MD_CTX;
-#elif defined(USE_NSS)
-// Forward declaration.
-struct SGNContextStr;
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-#include <Security/cssm.h>
-#endif
-
+#include <memory>
 #include <vector>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
+#include "build/build_config.h"
 #include "crypto/crypto_export.h"
+#include "starboard/types.h"
 
-#if defined(OS_WIN)
-#include "crypto/scoped_capi_types.h"
-#endif
+// Forward declaration for openssl/*.h
+typedef struct env_md_ctx_st EVP_MD_CTX;
 
 namespace crypto {
 
 class RSAPrivateKey;
 
 // Signs data using a bare private key (as opposed to a full certificate).
-// Currently can only sign data using SHA-1 with RSA encryption.
+// Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5.
 class CRYPTO_EXPORT SignatureCreator {
  public:
+  // The set of supported hash functions. Extend as required.
+  enum HashAlgorithm {
+    SHA1,
+    SHA256,
+  };
+
   ~SignatureCreator();
 
   // Create an instance. The caller must ensure that the provided PrivateKey
-  // instance outlives the created SignatureCreator.
-  static SignatureCreator* Create(RSAPrivateKey* key);
+  // instance outlives the created SignatureCreator. Uses the HashAlgorithm
+  // specified.
+  static std::unique_ptr<SignatureCreator> Create(RSAPrivateKey* key,
+                                                  HashAlgorithm hash_alg);
+
+  // Signs the precomputed |hash_alg| digest |data| using private |key| as
+  // specified in PKCS #1 v1.5.
+  static bool Sign(RSAPrivateKey* key,
+                   HashAlgorithm hash_alg,
+                   const uint8_t* data,
+                   int data_len,
+                   std::vector<uint8_t>* signature);
 
   // Update the signature with more data.
-  bool Update(const uint8* data_part, int data_part_len);
+  bool Update(const uint8_t* data_part, int data_part_len);
 
   // Finalize the signature.
-  bool Final(std::vector<uint8>* signature);
+  bool Final(std::vector<uint8_t>* signature);
 
  private:
   // Private constructor. Use the Create() method instead.
   SignatureCreator();
 
-  RSAPrivateKey* key_;
-
-#if defined(USE_OPENSSL)
   EVP_MD_CTX* sign_context_;
-#elif defined(USE_NSS)
-  SGNContextStr* sign_context_;
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-  CSSM_CC_HANDLE sig_handle_;
-#elif defined(OS_WIN)
-  ScopedHCRYPTHASH hash_object_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(SignatureCreator);
 };
diff --git a/src/crypto/signature_creator_mac.cc b/src/crypto/signature_creator_mac.cc
deleted file mode 100644
index cdc34f8..0000000
--- a/src/crypto/signature_creator_mac.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 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/signature_creator.h"
-
-#include <stdlib.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/cssm_init.h"
-#include "crypto/rsa_private_key.h"
-
-namespace crypto {
-
-// static
-SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
-  scoped_ptr<SignatureCreator> result(new SignatureCreator);
-  result->key_ = key;
-
-  CSSM_RETURN crtn;
-  crtn = CSSM_CSP_CreateSignatureContext(GetSharedCSPHandle(),
-                                         CSSM_ALGID_SHA1WithRSA,
-                                         NULL,
-                                         key->key(),
-                                         &result->sig_handle_);
-  if (crtn) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  crtn = CSSM_SignDataInit(result->sig_handle_);
-  if (crtn) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-SignatureCreator::SignatureCreator() : key_(NULL), sig_handle_(0) {
-  EnsureCSSMInit();
-}
-
-SignatureCreator::~SignatureCreator() {
-  CSSM_RETURN crtn;
-  if (sig_handle_) {
-    crtn = CSSM_DeleteContext(sig_handle_);
-    DCHECK_EQ(CSSM_OK, crtn);
-  }
-}
-
-bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
-  CSSM_DATA data;
-  data.Data = const_cast<uint8*>(data_part);
-  data.Length = data_part_len;
-  CSSM_RETURN crtn = CSSM_SignDataUpdate(sig_handle_, &data, 1);
-  DCHECK_EQ(CSSM_OK, crtn);
-  return true;
-}
-
-bool SignatureCreator::Final(std::vector<uint8>* signature) {
-  ScopedCSSMData sig;
-  CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, sig);
-
-  if (crtn) {
-    NOTREACHED();
-    return false;
-  }
-
-  signature->assign(sig->Data, sig->Data + sig->Length);
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_creator_nss.cc b/src/crypto/signature_creator_nss.cc
deleted file mode 100644
index 3a30efb..0000000
--- a/src/crypto/signature_creator_nss.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2012 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/signature_creator.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <stdlib.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/nss_util.h"
-#include "crypto/rsa_private_key.h"
-
-namespace crypto {
-
-SignatureCreator::~SignatureCreator() {
-  if (sign_context_) {
-    SGN_DestroyContext(sign_context_, PR_TRUE);
-    sign_context_ = NULL;
-  }
-}
-
-// static
-SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
-  scoped_ptr<SignatureCreator> result(new SignatureCreator);
-  result->key_ = key;
-
-  result->sign_context_ = SGN_NewContext(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION,
-      key->key());
-  if (!result->sign_context_) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  SECStatus rv = SGN_Begin(result->sign_context_);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
-  // TODO(wtc): Remove this const_cast when we require NSS 3.12.5.
-  // See NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=518255
-  SECStatus rv = SGN_Update(sign_context_,
-                            const_cast<unsigned char*>(data_part),
-                            data_part_len);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-bool SignatureCreator::Final(std::vector<uint8>* signature) {
-  SECItem signature_item;
-  SECStatus rv = SGN_End(sign_context_, &signature_item);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  signature->assign(signature_item.data,
-                    signature_item.data + signature_item.len);
-  SECITEM_FreeItem(&signature_item, PR_FALSE);
-  return true;
-}
-
-SignatureCreator::SignatureCreator()
-    : key_(NULL),
-      sign_context_(NULL) {
-  EnsureNSSInit();
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_creator_openssl.cc b/src/crypto/signature_creator_openssl.cc
deleted file mode 100644
index fa9ba07..0000000
--- a/src/crypto/signature_creator_openssl.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 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/signature_creator.h"
-
-#include <openssl/evp.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "crypto/openssl_util.h"
-#include "crypto/rsa_private_key.h"
-
-namespace crypto {
-
-// static
-SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  scoped_ptr<SignatureCreator> result(new SignatureCreator);
-  result->key_ = key;
-  if (!EVP_SignInit_ex(result->sign_context_, EVP_sha1(), NULL))
-    return NULL;
-  return result.release();
-}
-
-SignatureCreator::SignatureCreator()
-    : sign_context_(EVP_MD_CTX_create()) {
-}
-
-SignatureCreator::~SignatureCreator() {
-  EVP_MD_CTX_destroy(sign_context_);
-}
-
-bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  return EVP_SignUpdate(sign_context_, data_part, data_part_len) == 1;
-}
-
-bool SignatureCreator::Final(std::vector<uint8>* signature) {
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  EVP_PKEY* key = key_->key();
-  signature->resize(EVP_PKEY_size(key));
-
-  unsigned int len = 0;
-  int rv = EVP_SignFinal(sign_context_, vector_as_array(signature), &len, key);
-  if (!rv) {
-    signature->clear();
-    return false;
-  }
-  signature->resize(len);
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_creator_unittest.cc b/src/crypto/signature_creator_unittest.cc
index 881de91..053137b 100644
--- a/src/crypto/signature_creator_unittest.cc
+++ b/src/crypto/signature_creator_unittest.cc
@@ -2,46 +2,115 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "crypto/signature_creator.h"
+
+#include <memory>
+#include <string>
 #include <vector>
 
-#include "base/memory/scoped_ptr.h"
+#include "base/sha1.h"
 #include "crypto/rsa_private_key.h"
-#include "crypto/signature_creator.h"
+#include "crypto/sha2.h"
 #include "crypto/signature_verifier.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(SignatureCreatorTest, BasicTest) {
   // Do a verify round trip.
-  scoped_ptr<crypto::RSAPrivateKey> key_original(
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
       crypto::RSAPrivateKey::Create(1024));
   ASSERT_TRUE(key_original.get());
 
-  std::vector<uint8> key_info;
+  std::vector<uint8_t> key_info;
   key_original->ExportPrivateKey(&key_info);
-  scoped_ptr<crypto::RSAPrivateKey> key(
+  std::unique_ptr<crypto::RSAPrivateKey> key(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
   ASSERT_TRUE(key.get());
 
-  scoped_ptr<crypto::SignatureCreator> signer(
-      crypto::SignatureCreator::Create(key.get()));
+  std::unique_ptr<crypto::SignatureCreator> signer(
+      crypto::SignatureCreator::Create(key.get(),
+                                       crypto::SignatureCreator::SHA1));
   ASSERT_TRUE(signer.get());
 
   std::string data("Hello, World!");
-  ASSERT_TRUE(signer->Update(reinterpret_cast<const uint8*>(data.c_str()),
+  ASSERT_TRUE(signer->Update(reinterpret_cast<const uint8_t*>(data.c_str()),
                              data.size()));
 
-  std::vector<uint8> signature;
+  std::vector<uint8_t> signature;
   ASSERT_TRUE(signer->Final(&signature));
 
-  std::vector<uint8> public_key_info;
+  std::vector<uint8_t> public_key_info;
   ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
 
   crypto::SignatureVerifier verifier;
-  ASSERT_TRUE(verifier.VerifyInit(
-      crypto::SignatureVerifier::RSA_PKCS1_SHA1, &signature.front(),
-      signature.size(), &public_key_info.front(), public_key_info.size()));
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  signature, public_key_info));
 
-  verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
-                        data.size());
+  verifier.VerifyUpdate(base::as_bytes(base::make_span(data)));
+  ASSERT_TRUE(verifier.VerifyFinal());
+}
+
+TEST(SignatureCreatorTest, SignDigestTest) {
+  // Do a verify round trip.
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
+      crypto::RSAPrivateKey::Create(1024));
+  ASSERT_TRUE(key_original.get());
+
+  std::vector<uint8_t> key_info;
+  key_original->ExportPrivateKey(&key_info);
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key.get());
+
+  std::string data("Hello, World!");
+  std::string sha1 = base::SHA1HashString(data);
+  // Sign sha1 of the input data.
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(crypto::SignatureCreator::Sign(
+      key.get(), crypto::SignatureCreator::SHA1,
+      reinterpret_cast<const uint8_t*>(sha1.c_str()), sha1.size(), &signature));
+
+  std::vector<uint8_t> public_key_info;
+  ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
+
+  // Verify the input data.
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  signature, public_key_info));
+
+  verifier.VerifyUpdate(base::as_bytes(base::make_span(data)));
+  ASSERT_TRUE(verifier.VerifyFinal());
+}
+
+TEST(SignatureCreatorTest, SignSHA256DigestTest) {
+  // Do a verify round trip.
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
+      crypto::RSAPrivateKey::Create(1024));
+  ASSERT_TRUE(key_original.get());
+
+  std::vector<uint8_t> key_info;
+  key_original->ExportPrivateKey(&key_info);
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key.get());
+
+  std::string data("Hello, World!");
+  std::string sha256 = crypto::SHA256HashString(data);
+  // Sign sha256 of the input data.
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(crypto::SignatureCreator::Sign(
+      key.get(), crypto::SignatureCreator::HashAlgorithm::SHA256,
+      reinterpret_cast<const uint8_t*>(sha256.c_str()), sha256.size(),
+      &signature));
+
+  std::vector<uint8_t> public_key_info;
+  ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
+
+  // Verify the input data.
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA256,
+                                  signature, public_key_info));
+
+  verifier.VerifyUpdate(base::as_bytes(base::make_span(data)));
   ASSERT_TRUE(verifier.VerifyFinal());
 }
diff --git a/src/crypto/signature_creator_win.cc b/src/crypto/signature_creator_win.cc
deleted file mode 100644
index 69e6513..0000000
--- a/src/crypto/signature_creator_win.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 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/signature_creator.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/rsa_private_key.h"
-
-namespace crypto {
-
-// static
-SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
-  scoped_ptr<SignatureCreator> result(new SignatureCreator);
-  result->key_ = key;
-
-  if (!CryptCreateHash(key->provider(), CALG_SHA1, 0, 0,
-                       result->hash_object_.receive())) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-SignatureCreator::SignatureCreator() : key_(NULL), hash_object_(0) {}
-
-SignatureCreator::~SignatureCreator() {}
-
-bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
-  if (!CryptHashData(hash_object_, data_part, data_part_len, 0)) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-bool SignatureCreator::Final(std::vector<uint8>* signature) {
-  DWORD signature_length = 0;
-  if (!CryptSignHash(hash_object_, AT_SIGNATURE, NULL, 0, NULL,
-                     &signature_length)) {
-    return false;
-  }
-
-  std::vector<uint8> temp;
-  temp.resize(signature_length);
-  if (!CryptSignHash(hash_object_, AT_SIGNATURE, NULL, 0, &temp.front(),
-                     &signature_length)) {
-    return false;
-  }
-
-  temp.resize(signature_length);
-  for (size_t i = temp.size(); i > 0; --i)
-    signature->push_back(temp[i - 1]);
-
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_verifier.cc b/src/crypto/signature_verifier.cc
new file mode 100644
index 0000000..fd29bdf
--- /dev/null
+++ b/src/crypto/signature_verifier.cc
@@ -0,0 +1,104 @@
+// 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 "crypto/signature_verifier.h"
+
+#include "base/logging.h"
+#include "crypto/openssl_util.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+
+namespace crypto {
+
+struct SignatureVerifier::VerifyContext {
+  bssl::ScopedEVP_MD_CTX ctx;
+};
+
+SignatureVerifier::SignatureVerifier() = default;
+
+SignatureVerifier::~SignatureVerifier() = default;
+
+bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
+                                   base::span<const uint8_t> signature,
+                                   base::span<const uint8_t> public_key_info) {
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+  int pkey_type = EVP_PKEY_NONE;
+  const EVP_MD* digest = nullptr;
+  switch (signature_algorithm) {
+    case RSA_PKCS1_SHA1:
+      pkey_type = EVP_PKEY_RSA;
+      digest = EVP_sha1();
+      break;
+    case RSA_PKCS1_SHA256:
+    case RSA_PSS_SHA256:
+      pkey_type = EVP_PKEY_RSA;
+      digest = EVP_sha256();
+      break;
+    case ECDSA_SHA256:
+      pkey_type = EVP_PKEY_EC;
+      digest = EVP_sha256();
+      break;
+  }
+  DCHECK_NE(EVP_PKEY_NONE, pkey_type);
+  DCHECK(digest);
+
+  if (verify_context_)
+    return false;
+
+  verify_context_.reset(new VerifyContext);
+  signature_.assign(signature.data(), signature.data() + signature.size());
+
+  CBS cbs;
+  CBS_init(&cbs, public_key_info.data(), public_key_info.size());
+  bssl::UniquePtr<EVP_PKEY> public_key(EVP_parse_public_key(&cbs));
+  if (!public_key || CBS_len(&cbs) != 0 ||
+      EVP_PKEY_id(public_key.get()) != pkey_type) {
+    return false;
+  }
+
+  EVP_PKEY_CTX* pkey_ctx;
+  if (!EVP_DigestVerifyInit(verify_context_->ctx.get(), &pkey_ctx, digest,
+                            nullptr, public_key.get())) {
+    return false;
+  }
+
+  if (signature_algorithm == RSA_PSS_SHA256) {
+    if (!EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+        !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, digest) ||
+        !EVP_PKEY_CTX_set_rsa_pss_saltlen(
+            pkey_ctx, -1 /* match digest and salt length */)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SignatureVerifier::VerifyUpdate(base::span<const uint8_t> data_part) {
+  DCHECK(verify_context_);
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), data_part.data(),
+                                  data_part.size());
+  DCHECK_EQ(rv, 1);
+}
+
+bool SignatureVerifier::VerifyFinal() {
+  DCHECK(verify_context_);
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), signature_.data(),
+                                 signature_.size());
+  DCHECK_EQ(static_cast<int>(!!rv), rv);
+  Reset();
+  return rv == 1;
+}
+
+void SignatureVerifier::Reset() {
+  verify_context_.reset();
+  signature_.clear();
+}
+
+}  // namespace crypto
diff --git a/src/crypto/signature_verifier.h b/src/crypto/signature_verifier.h
index e181330..02fc400 100644
--- a/src/crypto/signature_verifier.h
+++ b/src/crypto/signature_verifier.h
@@ -5,16 +5,13 @@
 #ifndef CRYPTO_SIGNATURE_VERIFIER_H_
 #define CRYPTO_SIGNATURE_VERIFIER_H_
 
-#include "build/build_config.h"
-
+#include <memory>
 #include <vector>
 
-#include "base/basictypes.h"
+#include "base/containers/span.h"
+#include "build/build_config.h"
 #include "crypto/crypto_export.h"
-
-#if !defined(USE_OPENSSL)
-typedef struct VFYContextStr VFYContext;
-#endif
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -22,19 +19,24 @@
 // (as opposed to a certificate).
 class CRYPTO_EXPORT SignatureVerifier {
  public:
-  SignatureVerifier();
-  ~SignatureVerifier();
-
+  // The set of supported signature algorithms. Extend as required.
   enum SignatureAlgorithm {
     RSA_PKCS1_SHA1,
     RSA_PKCS1_SHA256,
     ECDSA_SHA256,
+    // This is RSA-PSS with SHA-256 as both signing hash and MGF-1 hash, and the
+    // salt length matching the hash length.
+    RSA_PSS_SHA256,
   };
 
+  SignatureVerifier();
+  ~SignatureVerifier();
+
   // Streaming interface:
 
   // Initiates a signature verification operation.  This should be followed
   // by one or more VerifyUpdate calls and a VerifyFinal call.
+  //
   // The signature is encoded according to the signature algorithm.
   //
   // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo
@@ -44,40 +46,24 @@
   //       algorithm            AlgorithmIdentifier,
   //       subjectPublicKey     BIT STRING  }
   bool VerifyInit(SignatureAlgorithm signature_algorithm,
-                  const uint8* signature,
-                  int signature_len,
-                  const uint8* public_key_info,
-                  int public_key_info_len);
+                  base::span<const uint8_t> signature,
+                  base::span<const uint8_t> public_key_info);
 
   // Feeds a piece of the data to the signature verifier.
-  void VerifyUpdate(const uint8* data_part, int data_part_len);
+  void VerifyUpdate(base::span<const uint8_t> data_part);
 
   // Concludes a signature verification operation.  Returns true if the
   // signature is valid.  Returns false if the signature is invalid or an
   // error occurred.
   bool VerifyFinal();
 
-  // Note: we can provide a one-shot interface if there is interest:
-  //   bool Verify(const uint8* data,
-  //               int data_len,
-  //               const uint8* signature_algorithm,
-  //               int signature_algorithm_len,
-  //               const uint8* signature,
-  //               int signature_len,
-  //               const uint8* public_key_info,
-  //               int public_key_info_len);
-
  private:
   void Reset();
 
-  std::vector<uint8> signature_;
+  std::vector<uint8_t> signature_;
 
-#if defined(USE_OPENSSL)
   struct VerifyContext;
-  VerifyContext* verify_context_;
-#else
-  VFYContext* vfy_context_;
-#endif
+  std::unique_ptr<VerifyContext> verify_context_;
 };
 
 }  // namespace crypto
diff --git a/src/crypto/signature_verifier_nss.cc b/src/crypto/signature_verifier_nss.cc
deleted file mode 100644
index 662e8f2..0000000
--- a/src/crypto/signature_verifier_nss.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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 "crypto/signature_verifier.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <stdlib.h>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-
-namespace crypto {
-
-SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) {
-  EnsureNSSInit();
-}
-
-SignatureVerifier::~SignatureVerifier() {
-  Reset();
-}
-
-bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
-                                   int signature_algorithm_len,
-                                   const uint8* signature,
-                                   int signature_len,
-                                   const uint8* public_key_info,
-                                   int public_key_info_len) {
-  signature_.assign(signature, signature + signature_len);
-
-  CERTSubjectPublicKeyInfo* spki = NULL;
-  SECItem spki_der;
-  spki_der.type = siBuffer;
-  spki_der.data = const_cast<uint8*>(public_key_info);
-  spki_der.len = public_key_info_len;
-  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
-  if (!spki)
-    return false;
-  SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
-  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
-  if (!public_key)
-    return false;
-
-  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-  if (!arena) {
-    SECKEY_DestroyPublicKey(public_key);
-    return false;
-  }
-
-  SECItem sig_alg_der;
-  sig_alg_der.type = siBuffer;
-  sig_alg_der.data = const_cast<uint8*>(signature_algorithm);
-  sig_alg_der.len = signature_algorithm_len;
-  SECAlgorithmID sig_alg_id;
-  SECStatus rv;
-  rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id,
-                              SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
-                              &sig_alg_der);
-  if (rv != SECSuccess) {
-    SECKEY_DestroyPublicKey(public_key);
-    PORT_FreeArena(arena, PR_TRUE);
-    return false;
-  }
-
-  SECItem sig;
-  sig.type = siBuffer;
-  sig.data = const_cast<uint8*>(signature);
-  sig.len = signature_len;
-  SECOidTag hash_alg_tag;
-  vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig,
-                                                  &sig_alg_id, &hash_alg_tag,
-                                                  NULL);
-  SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
-  PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
-  if (!vfy_context_) {
-    // A corrupted RSA signature could be detected without the data, so
-    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
-    // (-8182).
-    return false;
-  }
-
-  rv = VFY_Begin(vfy_context_);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  return true;
-}
-
-void SignatureVerifier::VerifyUpdate(const uint8* data_part,
-                                     int data_part_len) {
-  SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
-  DCHECK_EQ(SECSuccess, rv);
-}
-
-bool SignatureVerifier::VerifyFinal() {
-  SECStatus rv = VFY_End(vfy_context_);
-  Reset();
-
-  // If signature verification fails, the error code is
-  // SEC_ERROR_BAD_SIGNATURE (-8182).
-  return (rv == SECSuccess);
-}
-
-void SignatureVerifier::Reset() {
-  if (vfy_context_) {
-    VFY_DestroyContext(vfy_context_, PR_TRUE);
-    vfy_context_ = NULL;
-  }
-  signature_.clear();
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_verifier_openssl.cc b/src/crypto/signature_verifier_openssl.cc
deleted file mode 100644
index 112c4e3..0000000
--- a/src/crypto/signature_verifier_openssl.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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 "crypto/signature_verifier.h"
-
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "crypto/openssl_util.h"
-
-namespace crypto {
-
-struct SignatureVerifier::VerifyContext {
-  ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key;
-  ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx;
-};
-
-SignatureVerifier::SignatureVerifier()
-    : verify_context_(NULL) {
-}
-
-SignatureVerifier::~SignatureVerifier() {
-  Reset();
-}
-
-bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
-                                   const uint8* signature,
-                                   int signature_len,
-                                   const uint8* public_key_info,
-                                   int public_key_info_len) {
-  DCHECK(!verify_context_);
-  verify_context_ = new VerifyContext;
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
-  const EVP_MD* digest = nullptr;
-  switch (signature_algorithm) {
-    case RSA_PKCS1_SHA1:
-      digest = EVP_sha1();
-      break;
-    case RSA_PKCS1_SHA256:
-      digest = EVP_sha256();
-      break;
-    case ECDSA_SHA256:
-      digest = EVP_sha256();
-      break;
-  }
-  DCHECK(digest);
-
-  signature_.assign(signature, signature + signature_len);
-
-  // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
-  char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info));
-  ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data,
-                                                       public_key_info_len));
-  if (!bio.get())
-    return false;
-
-  verify_context_->public_key.reset(d2i_PUBKEY_bio(bio.get(), NULL));
-  if (!verify_context_->public_key.get())
-    return false;
-
-  verify_context_->ctx.reset(EVP_MD_CTX_create());
-  int rv = EVP_VerifyInit_ex(verify_context_->ctx.get(), digest, NULL);
-  return rv == 1;
-}
-
-void SignatureVerifier::VerifyUpdate(const uint8* data_part,
-                                     int data_part_len) {
-  DCHECK(verify_context_);
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  int rv = EVP_VerifyUpdate(verify_context_->ctx.get(),
-                            data_part, data_part_len);
-  DCHECK_EQ(rv, 1);
-}
-
-bool SignatureVerifier::VerifyFinal() {
-  DCHECK(verify_context_);
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  int rv = EVP_VerifyFinal(verify_context_->ctx.get(),
-                           vector_as_array(&signature_), signature_.size(),
-                           verify_context_->public_key.get());
-  DCHECK_GE(rv, 0);
-  Reset();
-  return rv == 1;
-}
-
-void SignatureVerifier::Reset() {
-  delete verify_context_;
-  verify_context_ = NULL;
-  signature_.clear();
-}
-
-}  // namespace crypto
diff --git a/src/crypto/signature_verifier_unittest.cc b/src/crypto/signature_verifier_unittest.cc
index a694a1f..58d5d3a 100644
--- a/src/crypto/signature_verifier_unittest.cc
+++ b/src/crypto/signature_verifier_unittest.cc
@@ -3,14 +3,20 @@
 // found in the LICENSE file.
 
 #include "crypto/signature_verifier.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "starboard/memory.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(SignatureVerifierTest, BasicTest) {
   // The input data in this test comes from real certificates.
   //
-  // tbs_certificate ("to-be-signed certificate", the part of a certificate
-  // that is signed), signature_algorithm, and algorithm come from the
-  // certificate of bugs.webkit.org.
+  // tbs_certificate ("to-be-signed certificate", the part of a certificate that
+  // is signed), signature, and algorithm come from the certificate of
+  // bugs.webkit.org.
   //
   // public_key_info comes from the certificate of the issuer, Go Daddy Secure
   // Certification Authority.
@@ -22,221 +28,383 @@
   //    TBSCertificate  ::=  SEQUENCE  {
   //        ...  -- omitted, not important
   //        }
-  const uint8 tbs_certificate[1017] = {
-    0x30, 0x82, 0x03, 0xf5,  // a SEQUENCE of length 1013 (0x3f5)
-    0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d,
-    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
-    0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
-    0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
-    0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31,
-    0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63,
-    0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18,
-    0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64,
-    0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
-    0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68,
-    0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
-    0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
-    0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
-    0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55,
-    0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79,
-    0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74,
-    0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
-    0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06,
-    0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32,
-    0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38,
-    0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
-    0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79,
-    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
-    0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
-    0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12,
-    0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70,
-    0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
-    0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49,
-    0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b,
-    0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72,
-    0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
-    0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72,
-    0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-    0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
-    0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28,
-    0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5,
-    0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0,
-    0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c,
-    0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1,
-    0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff,
-    0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39,
-    0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca,
-    0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1,
-    0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb,
-    0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e,
-    0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30,
-    0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02,
-    0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
-    0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16,
-    0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,
-    0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57,
-    0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0,
-    0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
-    0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73,
-    0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
-    0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f,
-    0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e,
-    0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e,
-    0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b,
-    0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd,
-    0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b,
-    0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74,
-    0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
-    0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
-    0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
-    0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
-    0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b,
-    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74,
-    0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
-    0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08,
-    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74,
-    0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
-    0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64,
-    0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69,
-    0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65,
-    0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74,
-    0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48,
-    0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5,
-    0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55,
-    0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32,
-    0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76,
-    0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04,
-    0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69,
-    0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69,
-    0x74, 0x2e, 0x6f, 0x72, 0x67
-  };
+  const uint8_t tbs_certificate[1017] = {
+      0x30, 0x82, 0x03, 0xf5,  // a SEQUENCE of length 1013 (0x3f5)
+      0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d,
+      0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+      0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+      0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+      0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31,
+      0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63,
+      0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18,
+      0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64,
+      0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
+      0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68,
+      0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
+      0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
+      0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
+      0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55,
+      0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79,
+      0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74,
+      0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
+      0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06,
+      0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32,
+      0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38,
+      0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+      0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79,
+      0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+      0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+      0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12,
+      0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70,
+      0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+      0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49,
+      0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b,
+      0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72,
+      0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+      0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72,
+      0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+      0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+      0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28,
+      0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5,
+      0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0,
+      0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c,
+      0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1,
+      0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff,
+      0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39,
+      0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca,
+      0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1,
+      0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb,
+      0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e,
+      0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30,
+      0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02,
+      0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+      0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16,
+      0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,
+      0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57,
+      0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0,
+      0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+      0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73,
+      0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
+      0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f,
+      0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e,
+      0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e,
+      0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b,
+      0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd,
+      0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b,
+      0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74,
+      0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+      0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
+      0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+      0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+      0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b,
+      0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74,
+      0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
+      0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08,
+      0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74,
+      0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+      0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64,
+      0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69,
+      0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65,
+      0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74,
+      0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48,
+      0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5,
+      0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55,
+      0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32,
+      0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76,
+      0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04,
+      0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69,
+      0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69,
+      0x74, 0x2e, 0x6f, 0x72, 0x67};
 
   // RSA signature, a big integer in the big-endian byte order.
-  const uint8 signature[256] = {
-    0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f,
-    0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37,
-    0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82,
-    0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01,
-    0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01,
-    0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98,
-    0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56,
-    0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8,
-    0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff,
-    0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d,
-    0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84,
-    0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8,
-    0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9,
-    0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2,
-    0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94,
-    0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3,
-    0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a,
-    0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e,
-    0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08,
-    0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd,
-    0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8,
-    0x3c, 0xd8, 0x48, 0x8a
-  };
+  const uint8_t signature[256] = {
+      0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f,
+      0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37,
+      0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82,
+      0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01,
+      0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01,
+      0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98,
+      0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56,
+      0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8,
+      0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff,
+      0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d,
+      0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84,
+      0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8,
+      0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9,
+      0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2,
+      0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94,
+      0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3,
+      0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a,
+      0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e,
+      0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08,
+      0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd,
+      0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8,
+      0x3c, 0xd8, 0x48, 0x8a};
 
   // The public key is specified as the following ASN.1 structure:
   //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
   //       algorithm            AlgorithmIdentifier,
   //       subjectPublicKey     BIT STRING  }
-  const uint8 public_key_info[294] = {
-    0x30, 0x82, 0x01, 0x22,  // a SEQUENCE of length 290 (0x122)
+  const uint8_t public_key_info[294] = {
+      0x30, 0x82, 0x01, 0x22,  // a SEQUENCE of length 290 (0x122)
       // algorithm
       0x30, 0x0d,  // a SEQUENCE of length 13
-        0x06, 0x09,  // an OBJECT IDENTIFIER of length 9
-          0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
-        0x05, 0x00,  // a NULL of length 0
+      0x06, 0x09,  // an OBJECT IDENTIFIER of length 9
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+      0x00,  // a NULL of length 0
       // subjectPublicKey
       0x03, 0x82, 0x01, 0x0f,  // a BIT STRING of length 271 (0x10f)
-        0x00,  // number of unused bits
-        0x30, 0x82, 0x01, 0x0a,  // a SEQUENCE of length 266 (0x10a)
-          // modulus
-          0x02, 0x82, 0x01, 0x01,  // an INTEGER of length 257 (0x101)
-            0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec,
-            0x32, 0x35, 0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61,
-            0x81, 0x59, 0x3b, 0x70, 0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7,
-            0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79, 0xe4, 0x3a, 0xed, 0x3c,
-            0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6, 0xb2, 0x87,
-            0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b,
-            0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9,
-            0x54, 0xeb, 0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95,
-            0xad, 0xef, 0xfb, 0xfe, 0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00,
-            0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42, 0x04, 0xce, 0xa7, 0x3f,
-            0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52, 0xa1, 0x69,
-            0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea,
-            0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48,
-            0xc7, 0x98, 0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66,
-            0x6d, 0x0a, 0x9c, 0xb3, 0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8,
-            0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9, 0x7a, 0x91, 0xc1, 0xa7,
-            0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65, 0x6e, 0x6a,
-            0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b,
-            0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0,
-            0xbf, 0x87, 0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5,
-            0x9d, 0xaf, 0x17, 0x31, 0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81,
-            0x36, 0x05, 0x89, 0x08, 0x98, 0xcf, 0x3a, 0xaf, 0x25, 0x87,
-            0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45, 0x8e, 0x97,
-            0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37,
-            0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe,
-            0x13, 0x94, 0xa3, 0x3f, 0x84, 0x0d, 0x4f,
-          // public exponent
-          0x02, 0x03,  // an INTEGER of length 3
-             0x01, 0x00, 0x01
-  };
+      0x00,                    // number of unused bits
+      0x30, 0x82, 0x01, 0x0a,  // a SEQUENCE of length 266 (0x10a)
+      // modulus
+      0x02, 0x82, 0x01, 0x01,  // an INTEGER of length 257 (0x101)
+      0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec, 0x32, 0x35,
+      0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61, 0x81, 0x59, 0x3b, 0x70,
+      0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7, 0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79,
+      0xe4, 0x3a, 0xed, 0x3c, 0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6,
+      0xb2, 0x87, 0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b,
+      0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9, 0x54, 0xeb,
+      0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95, 0xad, 0xef, 0xfb, 0xfe,
+      0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00, 0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42,
+      0x04, 0xce, 0xa7, 0x3f, 0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52,
+      0xa1, 0x69, 0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea,
+      0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48, 0xc7, 0x98,
+      0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66, 0x6d, 0x0a, 0x9c, 0xb3,
+      0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8, 0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9,
+      0x7a, 0x91, 0xc1, 0xa7, 0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65,
+      0x6e, 0x6a, 0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b,
+      0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0, 0xbf, 0x87,
+      0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5, 0x9d, 0xaf, 0x17, 0x31,
+      0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81, 0x36, 0x05, 0x89, 0x08, 0x98, 0xcf,
+      0x3a, 0xaf, 0x25, 0x87, 0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45,
+      0x8e, 0x97, 0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37,
+      0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe, 0x13, 0x94,
+      0xa3, 0x3f, 0x84, 0x0d, 0x4f,
+      // public exponent
+      0x02, 0x03,  // an INTEGER of length 3
+      0x01, 0x00, 0x01};
 
   // We use the signature verifier to perform four signature verification
   // tests.
   crypto::SignatureVerifier verifier;
-  bool ok;
 
-  // Test 1: feed all of the data to the verifier at once (a single
+  // Test  1: feed all of the data to the verifier at once (a single
   // VerifyUpdate call).
-  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
-                           sizeof(signature), public_key_info,
-                           sizeof(public_key_info));
-  EXPECT_TRUE(ok);
-  verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate));
-  ok = verifier.VerifyFinal();
-  EXPECT_TRUE(ok);
+  EXPECT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  signature, public_key_info));
+  verifier.VerifyUpdate(tbs_certificate);
+  EXPECT_TRUE(verifier.VerifyFinal());
 
   // Test 2: feed the data to the verifier in three parts (three VerifyUpdate
   // calls).
-  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
-                           sizeof(signature), public_key_info,
-                           sizeof(public_key_info));
-  EXPECT_TRUE(ok);
-  verifier.VerifyUpdate(tbs_certificate,       256);
-  verifier.VerifyUpdate(tbs_certificate + 256, 256);
-  verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512);
-  ok = verifier.VerifyFinal();
-  EXPECT_TRUE(ok);
+  EXPECT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  signature, public_key_info));
+  verifier.VerifyUpdate(base::make_span(tbs_certificate, 256));
+  verifier.VerifyUpdate(base::make_span(tbs_certificate + 256, 256));
+  verifier.VerifyUpdate(
+      base::make_span(tbs_certificate + 512, sizeof(tbs_certificate) - 512));
+  EXPECT_TRUE(verifier.VerifyFinal());
 
   // Test 3: verify the signature with incorrect data.
-  uint8 bad_tbs_certificate[sizeof(tbs_certificate)];
-  memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate));
+  uint8_t bad_tbs_certificate[sizeof(tbs_certificate)];
+  SbMemoryCopy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate));
   bad_tbs_certificate[10] += 1;  // Corrupt one byte of the data.
-  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
-                           sizeof(signature), public_key_info,
-                           sizeof(public_key_info));
-  EXPECT_TRUE(ok);
-  verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate));
-  ok = verifier.VerifyFinal();
-  EXPECT_FALSE(ok);
+  EXPECT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  signature, public_key_info));
+  verifier.VerifyUpdate(bad_tbs_certificate);
+  EXPECT_FALSE(verifier.VerifyFinal());
 
   // Test 4: verify a bad signature.
-  uint8 bad_signature[sizeof(signature)];
-  memcpy(bad_signature, signature, sizeof(signature));
+  uint8_t bad_signature[sizeof(signature)];
+  SbMemoryCopy(bad_signature, signature, sizeof(signature));
   bad_signature[10] += 1;  // Corrupt one byte of the signature.
-  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
-                           bad_signature, sizeof(bad_signature),
-                           public_key_info, sizeof(public_key_info));
+  EXPECT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                  bad_signature, public_key_info));
+  verifier.VerifyUpdate(tbs_certificate);
+  EXPECT_FALSE(verifier.VerifyFinal());
 
-  // A crypto library (e.g., NSS) may detect that the signature is corrupted
-  // and cause VerifyInit to return false, so it is fine for 'ok' to be false.
-  if (ok) {
-    verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate));
-    ok = verifier.VerifyFinal();
-    EXPECT_FALSE(ok);
+  // Test 5: import an invalid key.
+  uint8_t bad_public_key_info[sizeof(public_key_info)];
+  SbMemoryCopy(bad_public_key_info, public_key_info, sizeof(public_key_info));
+  bad_public_key_info[0] += 1;  // Corrupt part of the SPKI syntax.
+  EXPECT_FALSE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                   signature, bad_public_key_info));
+
+  // Test 6: import a key with extra data.
+  uint8_t long_public_key_info[sizeof(public_key_info) + 5];
+  SbMemorySet(long_public_key_info, 0, sizeof(long_public_key_info));
+  SbMemoryCopy(long_public_key_info, public_key_info, sizeof(public_key_info));
+  EXPECT_FALSE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                                   signature, long_public_key_info));
+}
+
+// The following RSA-PSS tests were generated via the following OpenSSL
+// commands:
+//
+// clang-format off
+// openssl genrsa -f4 -out key.pem 2048
+// openssl rsa -in key.pem -pubout -outform der | xxd -i > spki.txt
+// openssl rand -out message 50
+// xxd -i message > message.txt
+// openssl dgst -sign key.pem -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 < message | xxd -i > sig-good.txt
+// openssl dgst -sign key.pem -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:33 < message | xxd -i > sig-bad-saltlen.txt
+// clang-format on
+
+namespace {
+
+// This is the public key corresponding to the following private key.
+//
+// -----BEGIN RSA PRIVATE KEY-----
+// MIIEowIBAAKCAQEArg5NXFRQQ5QU7dcqqIjZwL4qy4AaJNSPfSPvXmFbK0hDXdp6
+// PdOZ2Wd+lQLZwb7ZQ2ZdqHVK3kZ2sVUlFmngIoEXNhVg+gW2zGPZ1YemwBMdZ/NW
+// V2xTX7Y3RrdR/kSccd9ByRTHKb+BCJ2XN5pHu91+LFchahW0lVPHz9DkBPUCThM2
+// I4ZosM3+AcO93RrrcbiQdpuY60Lfg9ZX7+1clM7zhiuOjWNY+FLN4+j4Ec8isiis
+// /V1LQyxRZ2t29kto47UJKu0Li7gUvEE1PS/nXBVgEqcSEBBKXa4ahsTqKWJAwvEH
+// xaH1t2qhVO1IHcf9FSv5k1T47H7XMLpO2OCPrwIDAQABAoIBAQCXA4exTOHa0Dcc
+// aGv1j87GAPimWX3VaKsaGzyKuZNdSTRR0MXwsI+yZa4Y4UFHbSuZ483s499SXPaM
+// Q2CLQs8ZgME/xmq+YojIavXL4wcVbUA9OY43CaCI0VLCQzmbj7HgxqCQMzvdh+8P
+// J5PUxUHpyHG5TNuL7EsiqG8bapT7ip2+IpKrKjr18gn3k0k9mLNJxK9Qr+CJphwo
+// eJgq0Kcjx3bfgDEpPzyvdd+J3e+jclOTYbk2HwJ0FVCrfgJedHFIWUytZoM5783g
+// knXzgDyKs65aUDjc/opidXp3WOqfNJUPSiofPYPdYQ26UI0vztL5MBkWCpl+d/55
+// BqxCdDlhAoGBANm90DFUca+7LdnDgj8mWtUIzr+XVzSD9tzOIpcjiPwEnxk8RHrM
+// aMHCAKZpbsnX/ikdc2I1OsirPgNFh1q30xgL7oCadzxlwfXnEM0Nff8RJKtN+yI6
+// +nRoOCDGCHBsaa2wyMYRbnanyRDLPIOP4eGQ6Hz/LQJBvhjRyTXlrUU/AoGBAMyj
+// ec1ySnlJ2S0JqPBCk14dRsEs/zStgFz1Wdmk7TMRBPUMyhWf8JwNrU5Ppm9biJMo
+// MKwkiFjzv/us4ne3wFRsTiKj4uiIwfji7/N2VpbEXSDGtonrX7hES4wQ/s+qr8XJ
+// 8ykHrZ9rPOY2lBhxOo+VYE3U6aspAY/qwK8WyumRAoGAMdl+/Iw0quLTkHNuMj75
+// tKQbkUl4sZE0x0B6Mtfz2J7GPeTKWMLLiPB9bZvdvWAx0//mFqnRF3f87orQfjhv
+// n6W7qL20ZqN1UHLiKc/Y9LhcCMwFnsSZ6mSh1P8Bl5t6ZkV+8bmz7H5lTe75n7Ul
+// JZsjXtqc11NtzgjZY/l9PckCgYAH6ZI+FVs30VkqWqNDlu9nxi4ELh84BDVgYsQ0
+// nCHnxZKxfusZZvPAtO6shnvi9mETf4xSO59iARq9OnQPOPWgzgc/Y6LUZuVJIE0y
+// 1rKGZdVL/SL1tjofP9TD96xCj1D4jtRuE7Ps5BKYvCeBwm8HOjldCQx357/9to/4
+// tSLnYQKBgG7STr94Slb3/BzzMxdMLCum1PH73/+IFxu1J0cXxYLP2zEhcSgqGIwm
+// aMgdu1L9eE6lJM99AWTEkpcUz8UFwNt+hZW+lZZpex77RMgRl9VCiwid1BNBSU/o
+// +lT1mlpDrPCNOge9n6Qvy5waBugB8uNS86w0UImYiKZr+8IQ4EdE
+// -----END RSA PRIVATE KEY-----
+const uint8_t kPSSPublicKey[] = {
+    0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+    0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
+    0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0x0e, 0x4d,
+    0x5c, 0x54, 0x50, 0x43, 0x94, 0x14, 0xed, 0xd7, 0x2a, 0xa8, 0x88, 0xd9,
+    0xc0, 0xbe, 0x2a, 0xcb, 0x80, 0x1a, 0x24, 0xd4, 0x8f, 0x7d, 0x23, 0xef,
+    0x5e, 0x61, 0x5b, 0x2b, 0x48, 0x43, 0x5d, 0xda, 0x7a, 0x3d, 0xd3, 0x99,
+    0xd9, 0x67, 0x7e, 0x95, 0x02, 0xd9, 0xc1, 0xbe, 0xd9, 0x43, 0x66, 0x5d,
+    0xa8, 0x75, 0x4a, 0xde, 0x46, 0x76, 0xb1, 0x55, 0x25, 0x16, 0x69, 0xe0,
+    0x22, 0x81, 0x17, 0x36, 0x15, 0x60, 0xfa, 0x05, 0xb6, 0xcc, 0x63, 0xd9,
+    0xd5, 0x87, 0xa6, 0xc0, 0x13, 0x1d, 0x67, 0xf3, 0x56, 0x57, 0x6c, 0x53,
+    0x5f, 0xb6, 0x37, 0x46, 0xb7, 0x51, 0xfe, 0x44, 0x9c, 0x71, 0xdf, 0x41,
+    0xc9, 0x14, 0xc7, 0x29, 0xbf, 0x81, 0x08, 0x9d, 0x97, 0x37, 0x9a, 0x47,
+    0xbb, 0xdd, 0x7e, 0x2c, 0x57, 0x21, 0x6a, 0x15, 0xb4, 0x95, 0x53, 0xc7,
+    0xcf, 0xd0, 0xe4, 0x04, 0xf5, 0x02, 0x4e, 0x13, 0x36, 0x23, 0x86, 0x68,
+    0xb0, 0xcd, 0xfe, 0x01, 0xc3, 0xbd, 0xdd, 0x1a, 0xeb, 0x71, 0xb8, 0x90,
+    0x76, 0x9b, 0x98, 0xeb, 0x42, 0xdf, 0x83, 0xd6, 0x57, 0xef, 0xed, 0x5c,
+    0x94, 0xce, 0xf3, 0x86, 0x2b, 0x8e, 0x8d, 0x63, 0x58, 0xf8, 0x52, 0xcd,
+    0xe3, 0xe8, 0xf8, 0x11, 0xcf, 0x22, 0xb2, 0x28, 0xac, 0xfd, 0x5d, 0x4b,
+    0x43, 0x2c, 0x51, 0x67, 0x6b, 0x76, 0xf6, 0x4b, 0x68, 0xe3, 0xb5, 0x09,
+    0x2a, 0xed, 0x0b, 0x8b, 0xb8, 0x14, 0xbc, 0x41, 0x35, 0x3d, 0x2f, 0xe7,
+    0x5c, 0x15, 0x60, 0x12, 0xa7, 0x12, 0x10, 0x10, 0x4a, 0x5d, 0xae, 0x1a,
+    0x86, 0xc4, 0xea, 0x29, 0x62, 0x40, 0xc2, 0xf1, 0x07, 0xc5, 0xa1, 0xf5,
+    0xb7, 0x6a, 0xa1, 0x54, 0xed, 0x48, 0x1d, 0xc7, 0xfd, 0x15, 0x2b, 0xf9,
+    0x93, 0x54, 0xf8, 0xec, 0x7e, 0xd7, 0x30, 0xba, 0x4e, 0xd8, 0xe0, 0x8f,
+    0xaf, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const uint8_t kPSSMessage[] = {
+    0x1e, 0x70, 0xbd, 0xeb, 0x24, 0xf2, 0x9d, 0x05, 0xc5, 0xb5,
+    0xf4, 0xca, 0xe6, 0x1d, 0x01, 0x97, 0x29, 0xf4, 0xe0, 0x7c,
+    0xfd, 0xcc, 0x97, 0x8d, 0xc2, 0xbb, 0x2d, 0x9b, 0x6b, 0x45,
+    0x06, 0xbd, 0x2c, 0x66, 0x10, 0x42, 0x73, 0x8d, 0x88, 0x9b,
+    0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f,
+};
+
+const uint8_t kPSSSignatureGood[] = {
+    0x12, 0xa7, 0x6d, 0x9e, 0x8a, 0xea, 0x28, 0xe0, 0x3f, 0x6f, 0x5a, 0xa4,
+    0x1b, 0x6a, 0x0a, 0x14, 0xba, 0xfa, 0x84, 0xf6, 0xb7, 0x3c, 0xc9, 0xd6,
+    0x84, 0xab, 0x1e, 0x77, 0x88, 0x53, 0x95, 0x43, 0x8e, 0x73, 0xe4, 0x21,
+    0xab, 0x69, 0xb2, 0x0c, 0x73, 0x4d, 0x98, 0x42, 0xbd, 0x65, 0xa2, 0x95,
+    0x0d, 0x76, 0xb2, 0xbd, 0xe5, 0x9a, 0x6e, 0x9f, 0x72, 0x7f, 0xdd, 0x1e,
+    0x9f, 0xda, 0xc8, 0x2e, 0xa3, 0xe6, 0x28, 0x03, 0x98, 0x5c, 0x13, 0xa7,
+    0x7d, 0x4e, 0xde, 0xea, 0x35, 0x1b, 0x35, 0x7e, 0xaa, 0x14, 0xf9, 0xfb,
+    0xac, 0x61, 0xd0, 0x44, 0x20, 0xd5, 0x52, 0x5b, 0x92, 0x8f, 0xe7, 0x37,
+    0xa2, 0x72, 0x7d, 0xe6, 0x0d, 0x81, 0x63, 0xcc, 0x0f, 0xbd, 0xde, 0x25,
+    0xe3, 0x3f, 0x89, 0x1b, 0x39, 0x64, 0xfa, 0x21, 0x1d, 0x0f, 0x9b, 0x8a,
+    0xc1, 0xad, 0x03, 0x49, 0x96, 0xff, 0x9f, 0x2d, 0x83, 0xee, 0x2d, 0x2a,
+    0x1e, 0xc5, 0x73, 0x9f, 0x5b, 0xde, 0xcb, 0xaf, 0x02, 0xbd, 0xc5, 0x9b,
+    0x78, 0xb9, 0x8e, 0x01, 0x75, 0x3c, 0xc9, 0x6e, 0x7d, 0x3e, 0x61, 0x62,
+    0xc4, 0x8c, 0x9e, 0x76, 0xed, 0x52, 0x5e, 0x80, 0x89, 0xa7, 0x75, 0x5e,
+    0xc6, 0x34, 0x97, 0x22, 0x40, 0xb5, 0x0c, 0x77, 0x09, 0x8c, 0xa8, 0xe9,
+    0xf6, 0x8d, 0xc0, 0x10, 0x78, 0x92, 0xa9, 0xc6, 0x68, 0xa3, 0x57, 0x6e,
+    0x73, 0xb5, 0x73, 0x8d, 0x8e, 0x21, 0xb1, 0xf3, 0xd0, 0x0a, 0x40, 0x68,
+    0xfc, 0x3c, 0xeb, 0xd3, 0x48, 0x4a, 0x44, 0xbd, 0xc0, 0x40, 0x5d, 0x9b,
+    0x40, 0x6f, 0x45, 0x98, 0x2b, 0xae, 0x58, 0xe8, 0x9d, 0x34, 0x49, 0xd2,
+    0xec, 0xdc, 0xd5, 0x98, 0xb4, 0x87, 0x8a, 0xcc, 0x41, 0x3e, 0xd7, 0xe6,
+    0x21, 0xd6, 0x4c, 0x89, 0xf1, 0xf4, 0x77, 0x40, 0x3f, 0x9a, 0x28, 0x25,
+    0x55, 0x7c, 0xf5, 0x0c,
+};
+
+const uint8_t kPSSSignatureBadSaltLength[] = {
+    0x6e, 0x61, 0xbe, 0x8a, 0x82, 0xbd, 0xed, 0xc6, 0xe4, 0x33, 0x91, 0xa4,
+    0x43, 0x57, 0x51, 0x7e, 0xa8, 0x18, 0xbf, 0x20, 0x98, 0xbc, 0x04, 0x50,
+    0x06, 0x1b, 0x0b, 0xb6, 0x43, 0xde, 0x58, 0x7f, 0x6b, 0xa5, 0x5e, 0x9d,
+    0xd1, 0x75, 0x03, 0xf5, 0x19, 0x8d, 0xdb, 0x2c, 0xd2, 0x9a, 0xf9, 0xbd,
+    0x82, 0x8d, 0x32, 0x9d, 0x7d, 0x70, 0x6f, 0x81, 0x95, 0x60, 0x1d, 0x62,
+    0x72, 0xf3, 0x95, 0x5b, 0x7a, 0x66, 0x7f, 0x45, 0x94, 0x0c, 0x07, 0xc8,
+    0xa7, 0x64, 0x38, 0x57, 0x1a, 0x64, 0x64, 0xf1, 0xe0, 0x45, 0xfe, 0x00,
+    0x11, 0x90, 0x57, 0x95, 0x15, 0x21, 0x10, 0x85, 0xc0, 0xbe, 0x53, 0x5b,
+    0x3b, 0xa3, 0x57, 0x99, 0x2b, 0x94, 0x6b, 0xbf, 0xa5, 0x55, 0x7d, 0x5a,
+    0xcb, 0xa2, 0x73, 0x6b, 0x5f, 0x7b, 0x3f, 0x10, 0x90, 0xd1, 0x26, 0x72,
+    0x5e, 0xad, 0xd1, 0x34, 0xe8, 0x8a, 0x33, 0xeb, 0xd2, 0xbf, 0x54, 0x92,
+    0xeb, 0x7c, 0xb9, 0x97, 0x80, 0x5a, 0x46, 0xc4, 0xbd, 0xf5, 0x7e, 0xd6,
+    0x20, 0x90, 0x92, 0xcb, 0x37, 0x85, 0x9d, 0x81, 0x0a, 0xd0, 0xa5, 0x73,
+    0x17, 0x7e, 0xe2, 0x91, 0xef, 0x35, 0x55, 0xc9, 0x5e, 0x87, 0x84, 0x11,
+    0xa4, 0x36, 0xf0, 0x2a, 0xa7, 0x7a, 0x83, 0x1d, 0x7a, 0x90, 0x69, 0x22,
+    0x5d, 0x3b, 0x30, 0x48, 0x46, 0xd2, 0xd3, 0x49, 0x23, 0x64, 0xa4, 0x6d,
+    0xd1, 0xef, 0xb9, 0x1b, 0xa4, 0xd1, 0x92, 0xdd, 0x8c, 0xb2, 0xaa, 0x9f,
+    0x6a, 0x2c, 0xc9, 0xdb, 0xa7, 0x35, 0x66, 0x92, 0x8b, 0x73, 0x11, 0x70,
+    0x2b, 0xf4, 0x34, 0x3f, 0x9e, 0x15, 0x3e, 0xc0, 0xac, 0x78, 0x6f, 0x74,
+    0x8a, 0x6b, 0xe4, 0xf2, 0x7b, 0x10, 0xca, 0x01, 0x3a, 0x3a, 0x88, 0x39,
+    0x34, 0xa8, 0x52, 0x4a, 0x76, 0x50, 0xef, 0xdb, 0x91, 0x3c, 0x4a, 0x5c,
+    0xe5, 0x43, 0x6f, 0x8e,
+};
+
+}  // namespace
+
+TEST(SignatureVerifierTest, VerifyRSAPSS) {
+  // Verify the test vector.
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PSS_SHA256,
+                                  kPSSSignatureGood, kPSSPublicKey));
+  verifier.VerifyUpdate(kPSSMessage);
+  EXPECT_TRUE(verifier.VerifyFinal());
+
+  // Verify the test vector byte-by-byte.
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PSS_SHA256,
+                                  kPSSSignatureGood, kPSSPublicKey));
+  for (uint8_t b : kPSSMessage) {
+    verifier.VerifyUpdate(base::make_span(&b, 1));
   }
+  EXPECT_TRUE(verifier.VerifyFinal());
+
+  // The bad salt length does not verify.
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PSS_SHA256,
+                                  kPSSSignatureBadSaltLength, kPSSPublicKey));
+  verifier.VerifyUpdate(kPSSMessage);
+  EXPECT_FALSE(verifier.VerifyFinal());
+
+  // Corrupt the message.
+  std::vector<uint8_t> message(std::begin(kPSSMessage), std::end(kPSSMessage));
+  message[0] ^= 1;
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PSS_SHA256,
+                                  kPSSSignatureGood, kPSSPublicKey));
+  verifier.VerifyUpdate(message);
+  EXPECT_FALSE(verifier.VerifyFinal());
+
+  // Corrupt the signature.
+  std::vector<uint8_t> signature(std::begin(kPSSSignatureGood),
+                                 std::end(kPSSSignatureGood));
+  signature[0] ^= 1;
+  ASSERT_TRUE(verifier.VerifyInit(crypto::SignatureVerifier::RSA_PSS_SHA256,
+                                  signature, kPSSPublicKey));
+  verifier.VerifyUpdate(kPSSMessage);
+  EXPECT_FALSE(verifier.VerifyFinal());
 }
diff --git a/src/crypto/symmetric_key.cc b/src/crypto/symmetric_key.cc
new file mode 100644
index 0000000..83369b3
--- /dev/null
+++ b/src/crypto/symmetric_key.cc
@@ -0,0 +1,141 @@
+// 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 "crypto/symmetric_key.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "starboard/types.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rand.h"
+
+namespace crypto {
+
+namespace {
+
+bool CheckDerivationParameters(SymmetricKey::Algorithm algorithm,
+                               size_t key_size_in_bits) {
+  switch (algorithm) {
+    case SymmetricKey::AES:
+      // Whitelist supported key sizes to avoid accidentally relying on
+      // algorithms available in NSS but not BoringSSL and vice
+      // versa. Note that BoringSSL does not support AES-192.
+      return key_size_in_bits == 128 || key_size_in_bits == 256;
+    case SymmetricKey::HMAC_SHA1:
+      return key_size_in_bits % 8 == 0 && key_size_in_bits != 0;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+}  // namespace
+
+SymmetricKey::~SymmetricKey() {
+  std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
+}
+
+// static
+std::unique_ptr<SymmetricKey> SymmetricKey::GenerateRandomKey(
+    Algorithm algorithm,
+    size_t key_size_in_bits) {
+  DCHECK_EQ(AES, algorithm);
+
+  // Whitelist supported key sizes to avoid accidentaly relying on
+  // algorithms available in NSS but not BoringSSL and vice
+  // versa. Note that BoringSSL does not support AES-192.
+  if (key_size_in_bits != 128 && key_size_in_bits != 256)
+    return nullptr;
+
+  size_t key_size_in_bytes = key_size_in_bits / 8;
+  DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
+
+  if (key_size_in_bytes == 0)
+    return nullptr;
+
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  uint8_t* key_data = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&key->key_, key_size_in_bytes + 1));
+
+  int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
+  return rv == 1 ? std::move(key) : nullptr;
+}
+
+// static
+std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+    Algorithm algorithm,
+    const std::string& password,
+    const std::string& salt,
+    size_t iterations,
+    size_t key_size_in_bits) {
+  if (!CheckDerivationParameters(algorithm, key_size_in_bits))
+    return nullptr;
+
+  size_t key_size_in_bytes = key_size_in_bits / 8;
+
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  uint8_t* key_data = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&key->key_, key_size_in_bytes + 1));
+
+  int rv = PKCS5_PBKDF2_HMAC_SHA1(
+      password.data(), password.length(),
+      reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
+      static_cast<unsigned>(iterations),
+      key_size_in_bytes, key_data);
+  return rv == 1 ? std::move(key) : nullptr;
+}
+
+// static
+std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
+    Algorithm algorithm,
+    const std::string& password,
+    const std::string& salt,
+    size_t cost_parameter,
+    size_t block_size,
+    size_t parallelization_parameter,
+    size_t max_memory_bytes,
+    size_t key_size_in_bits) {
+  if (!CheckDerivationParameters(algorithm, key_size_in_bits))
+    return nullptr;
+
+  size_t key_size_in_bytes = key_size_in_bits / 8;
+
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  uint8_t* key_data = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&key->key_, key_size_in_bytes + 1));
+
+  int rv = EVP_PBE_scrypt(password.data(), password.length(),
+                          reinterpret_cast<const uint8_t*>(salt.data()),
+                          salt.length(), cost_parameter, block_size,
+                          parallelization_parameter, max_memory_bytes, key_data,
+                          key_size_in_bytes);
+  return rv == 1 ? std::move(key) : nullptr;
+}
+
+// static
+std::unique_ptr<SymmetricKey> SymmetricKey::Import(Algorithm algorithm,
+                                                   const std::string& raw_key) {
+  if (algorithm == AES) {
+    // Whitelist supported key sizes to avoid accidentaly relying on
+    // algorithms available in NSS but not BoringSSL and vice
+    // versa. Note that BoringSSL does not support AES-192.
+    if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
+      return nullptr;
+  }
+
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  key->key_ = raw_key;
+  return key;
+}
+
+SymmetricKey::SymmetricKey() = default;
+
+}  // namespace crypto
diff --git a/src/crypto/symmetric_key.h b/src/crypto/symmetric_key.h
index cce2a9b..ae4e8d6 100644
--- a/src/crypto/symmetric_key.h
+++ b/src/crypto/symmetric_key.h
@@ -5,18 +5,13 @@
 #ifndef CRYPTO_SYMMETRIC_KEY_H_
 #define CRYPTO_SYMMETRIC_KEY_H_
 
+#include <memory>
 #include <string>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
+#include "build/build_config.h"
 #include "crypto/crypto_export.h"
-
-#if defined(NACL_WIN64)
-// See comments for crypto_nacl_win64 in crypto.gyp.
-// Must test for NACL_WIN64 before OS_WIN since former is a subset of latter.
-#include "crypto/scoped_capi_types.h"
-#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-#include "crypto/scoped_nss_types.h"
-#endif
+#include "starboard/types.h"
 
 namespace crypto {
 
@@ -36,66 +31,53 @@
   // Generates a random key suitable to be used with |algorithm| and of
   // |key_size_in_bits| bits. |key_size_in_bits| must be a multiple of 8.
   // The caller is responsible for deleting the returned SymmetricKey.
-  static SymmetricKey* GenerateRandomKey(Algorithm algorithm,
-                                         size_t key_size_in_bits);
+  static std::unique_ptr<SymmetricKey> GenerateRandomKey(
+      Algorithm algorithm,
+      size_t key_size_in_bits);
 
   // Derives a key from the supplied password and salt using PBKDF2, suitable
   // for use with specified |algorithm|. Note |algorithm| is not the algorithm
   // used to derive the key from the password. |key_size_in_bits| must be a
   // multiple of 8. The caller is responsible for deleting the returned
   // SymmetricKey.
-  static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm,
-                                             const std::string& password,
-                                             const std::string& salt,
-                                             size_t iterations,
-                                             size_t key_size_in_bits);
+  static std::unique_ptr<SymmetricKey> DeriveKeyFromPasswordUsingPbkdf2(
+      Algorithm algorithm,
+      const std::string& password,
+      const std::string& salt,
+      size_t iterations,
+      size_t key_size_in_bits);
+
+  // Derives a key from the supplied password and salt using scrypt, suitable
+  // for use with specified |algorithm|. Note |algorithm| is not the algorithm
+  // used to derive the key from the password. |cost_parameter|, |block_size|,
+  // and |parallelization_parameter| correspond to the parameters |N|, |r|, and
+  // |p| from the scrypt specification (see RFC 7914). |key_size_in_bits| must
+  // be a multiple of 8. The caller is responsible for deleting the returned
+  // SymmetricKey.
+  static std::unique_ptr<SymmetricKey> DeriveKeyFromPasswordUsingScrypt(
+      Algorithm algorithm,
+      const std::string& password,
+      const std::string& salt,
+      size_t cost_parameter,
+      size_t block_size,
+      size_t parallelization_parameter,
+      size_t max_memory_bytes,
+      size_t key_size_in_bits);
 
   // Imports an array of key bytes in |raw_key|. This key may have been
-  // generated by GenerateRandomKey or DeriveKeyFromPassword and exported with
-  // GetRawKey, or via another compatible method. The key must be of suitable
-  // size for use with |algorithm|. The caller owns the returned SymmetricKey.
-  static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key);
+  // generated by GenerateRandomKey or DeriveKeyFromPassword{Pbkdf2,Scrypt} and
+  // exported with key(). The key must be of suitable size for use with
+  // |algorithm|. The caller owns the returned SymmetricKey.
+  static std::unique_ptr<SymmetricKey> Import(Algorithm algorithm,
+                                              const std::string& raw_key);
 
-#if defined(USE_OPENSSL)
-  const std::string& key() { return key_; }
-#elif defined(NACL_WIN64)
-  HCRYPTKEY key() const { return key_.get(); }
-#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-  PK11SymKey* key() const { return key_.get(); }
-#endif
-
-  // Extracts the raw key from the platform specific data.
-  // Warning: |raw_key| holds the raw key as bytes and thus must be handled
-  // carefully.
-  bool GetRawKey(std::string* raw_key);
-
-#if defined(OS_CHROMEOS)
-  // Creates symmetric key from NSS key. Takes over the ownership of |key|.
-  static SymmetricKey* CreateFromKey(PK11SymKey* key);
-#endif
+  // Returns the raw platform specific key data.
+  const std::string& key() const { return key_; }
 
  private:
-#if defined(USE_OPENSSL)
-  SymmetricKey() {}
+  SymmetricKey();
+
   std::string key_;
-#elif defined(NACL_WIN64)
-  SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key,
-               const void* key_data, size_t key_size_in_bytes);
-
-  ScopedHCRYPTPROV provider_;
-  ScopedHCRYPTKEY key_;
-
-  // Contains the raw key, if it is known during initialization and when it
-  // is likely that the associated |provider_| will be unable to export the
-  // |key_|. This is the case of HMAC keys when the key size exceeds 16 bytes
-  // when using the default RSA provider.
-  // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey
-  // fails with NTE_BAD_KEY/NTE_BAD_LEN
-  std::string raw_key_;
-#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-  explicit SymmetricKey(PK11SymKey* key);
-  ScopedPK11SymKey key_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(SymmetricKey);
 };
diff --git a/src/crypto/symmetric_key_openssl.cc b/src/crypto/symmetric_key_openssl.cc
deleted file mode 100644
index 899a942..0000000
--- a/src/crypto/symmetric_key_openssl.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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 "crypto/symmetric_key.h"
-
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_util.h"
-#include "crypto/openssl_util.h"
-
-namespace crypto {
-
-SymmetricKey::~SymmetricKey() {
-  std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
-}
-
-// static
-SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
-                                              size_t key_size_in_bits) {
-  DCHECK_EQ(AES, algorithm);
-  size_t key_size_in_bytes = key_size_in_bits / 8;
-  DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
-
-  if (key_size_in_bytes == 0)
-    return NULL;
-
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  scoped_ptr<SymmetricKey> key(new SymmetricKey);
-  uint8* key_data =
-      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
-
-  int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
-  return rv == 1 ? key.release() : NULL;
-}
-
-// static
-SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
-                                                  const std::string& password,
-                                                  const std::string& salt,
-                                                  size_t iterations,
-                                                  size_t key_size_in_bits) {
-  DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
-  size_t key_size_in_bytes = key_size_in_bits / 8;
-  DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
-
-  if (key_size_in_bytes == 0)
-    return NULL;
-
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  scoped_ptr<SymmetricKey> key(new SymmetricKey);
-  uint8* key_data =
-      reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
-  int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
-                                  reinterpret_cast<const uint8*>(salt.data()),
-                                  salt.length(), iterations,
-                                  static_cast<int>(key_size_in_bytes),
-                                  key_data);
-  return rv == 1 ? key.release() : NULL;
-}
-
-// static
-SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
-                                   const std::string& raw_key) {
-  scoped_ptr<SymmetricKey> key(new SymmetricKey);
-  key->key_ = raw_key;
-  return key.release();
-}
-
-bool SymmetricKey::GetRawKey(std::string* raw_key) {
-  *raw_key = key_;
-  return true;
-}
-
-}  // namespace crypto
diff --git a/src/crypto/symmetric_key_unittest.cc b/src/crypto/symmetric_key_unittest.cc
index 389d7f5..6bef6ca 100644
--- a/src/crypto/symmetric_key_unittest.cc
+++ b/src/crypto/symmetric_key_unittest.cc
@@ -4,65 +4,51 @@
 
 #include "crypto/symmetric_key.h"
 
+#include <memory>
 #include <string>
 
-#include "base/memory/scoped_ptr.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(SymmetricKeyTest, GenerateRandomKey) {
-  scoped_ptr<crypto::SymmetricKey> key(
+  std::unique_ptr<crypto::SymmetricKey> key(
       crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
-  ASSERT_TRUE(NULL != key.get());
-  std::string raw_key;
-  EXPECT_TRUE(key->GetRawKey(&raw_key));
-  EXPECT_EQ(32U, raw_key.size());
+  ASSERT_TRUE(key);
+  EXPECT_EQ(32U, key->key().size());
 
   // Do it again and check that the keys are different.
   // (Note: this has a one-in-10^77 chance of failure!)
-  scoped_ptr<crypto::SymmetricKey> key2(
+  std::unique_ptr<crypto::SymmetricKey> key2(
       crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
-  ASSERT_TRUE(NULL != key2.get());
-  std::string raw_key2;
-  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
-  EXPECT_EQ(32U, raw_key2.size());
-  EXPECT_NE(raw_key, raw_key2);
+  ASSERT_TRUE(key2);
+  EXPECT_EQ(32U, key2->key().size());
+  EXPECT_NE(key->key(), key2->key());
 }
 
 TEST(SymmetricKeyTest, ImportGeneratedKey) {
-  scoped_ptr<crypto::SymmetricKey> key1(
+  std::unique_ptr<crypto::SymmetricKey> key1(
       crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
-  ASSERT_TRUE(NULL != key1.get());
-  std::string raw_key1;
-  EXPECT_TRUE(key1->GetRawKey(&raw_key1));
+  ASSERT_TRUE(key1);
 
-  scoped_ptr<crypto::SymmetricKey> key2(
-      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1));
-  ASSERT_TRUE(NULL != key2.get());
+  std::unique_ptr<crypto::SymmetricKey> key2(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, key1->key()));
+  ASSERT_TRUE(key2);
 
-  std::string raw_key2;
-  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
-
-  EXPECT_EQ(raw_key1, raw_key2);
+  EXPECT_EQ(key1->key(), key2->key());
 }
 
 TEST(SymmetricKeyTest, ImportDerivedKey) {
-  scoped_ptr<crypto::SymmetricKey> key1(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+  std::unique_ptr<crypto::SymmetricKey> key1(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160));
-  ASSERT_TRUE(NULL != key1.get());
-  std::string raw_key1;
-  EXPECT_TRUE(key1->GetRawKey(&raw_key1));
+  ASSERT_TRUE(key1);
 
-  scoped_ptr<crypto::SymmetricKey> key2(
-      crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1));
-  ASSERT_TRUE(NULL != key2.get());
+  std::unique_ptr<crypto::SymmetricKey> key2(crypto::SymmetricKey::Import(
+      crypto::SymmetricKey::HMAC_SHA1, key1->key()));
+  ASSERT_TRUE(key2);
 
-  std::string raw_key2;
-  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
-
-  EXPECT_EQ(raw_key1, raw_key2);
+  EXPECT_EQ(key1->key(), key2->key());
 }
 
 struct PBKDF2TestVector {
@@ -71,67 +57,77 @@
   const char* salt;
   unsigned int rounds;
   unsigned int key_size_in_bits;
-  const char* expected;  // ASCII encoded hex bytes
+  const char* expected;  // ASCII encoded hex bytes.
 };
 
-class SymmetricKeyDeriveKeyFromPasswordTest
-    : public testing::TestWithParam<PBKDF2TestVector> {
+struct ScryptTestVector {
+  crypto::SymmetricKey::Algorithm algorithm;
+  const char* password;
+  const char* salt;
+  unsigned int cost_parameter;
+  unsigned int block_size;
+  unsigned int parallelization_parameter;
+  unsigned int key_size_in_bits;
+  const char* expected;  // ASCII encoded hex bytes.
 };
 
-TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) {
+class SymmetricKeyDeriveKeyFromPasswordUsingPbkdf2Test
+    : public testing::TestWithParam<PBKDF2TestVector> {};
+
+class SymmetricKeyDeriveKeyFromPasswordUsingScryptTest
+    : public testing::TestWithParam<ScryptTestVector> {};
+
+TEST_P(SymmetricKeyDeriveKeyFromPasswordUsingPbkdf2Test,
+       DeriveKeyFromPasswordUsingPbkdf2) {
   PBKDF2TestVector test_data(GetParam());
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The OS X crypto libraries have minimum salt and iteration requirements
-  // so some of the tests below will cause them to barf. Skip these.
-  if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) {
-    VLOG(1) << "Skipped test vector for " << test_data.expected;
-    return;
-  }
-#endif  // OS_MACOSX
-
-  scoped_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
-          test_data.algorithm,
-          test_data.password, test_data.salt,
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          test_data.algorithm, test_data.password, test_data.salt,
           test_data.rounds, test_data.key_size_in_bits));
-  ASSERT_TRUE(NULL != key.get());
+  ASSERT_TRUE(key);
 
-  std::string raw_key;
-  key->GetRawKey(&raw_key);
+  const std::string& raw_key = key->key();
   EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size());
   EXPECT_EQ(test_data.expected,
-            StringToLowerASCII(base::HexEncode(raw_key.data(),
+            base::ToLowerASCII(base::HexEncode(raw_key.data(),
                                                raw_key.size())));
 }
 
-static const PBKDF2TestVector kTestVectors[] = {
-  // These tests come from
-  // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "salt",
-    1,
-    160,
-    "0c60c80f961f0e71f3a9b524af6012062fe037a6",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "salt",
-    2,
-    160,
-    "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "salt",
-    4096,
-    160,
-    "4b007901b765489abead49d926f721d065a429c1",
-  },
-  // This test takes over 30s to run on the trybots.
+TEST_P(SymmetricKeyDeriveKeyFromPasswordUsingScryptTest,
+       DeriveKeyFromPasswordUsingScrypt) {
+  const int kScryptMaxMemoryBytes = 128 * 1024 * 1024;  // 128 MiB.
+
+  ScryptTestVector test_data(GetParam());
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
+          test_data.algorithm, test_data.password, test_data.salt,
+          test_data.cost_parameter, test_data.block_size,
+          test_data.parallelization_parameter, kScryptMaxMemoryBytes,
+          test_data.key_size_in_bits));
+  ASSERT_TRUE(key);
+
+  const std::string& raw_key = key->key();
+  EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size());
+  EXPECT_EQ(test_data.expected, base::ToLowerASCII(base::HexEncode(
+                                    raw_key.data(), raw_key.size())));
+}
+
+static const PBKDF2TestVector kTestVectorsPbkdf2[] = {
+    // These tests come from
+    // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt.
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "salt", 1, 160,
+        "0c60c80f961f0e71f3a9b524af6012062fe037a6",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "salt", 2, 160,
+        "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "salt", 4096, 160,
+        "4b007901b765489abead49d926f721d065a429c1",
+    },
+// This test takes over 30s to run on the trybots.
 #if 0
   {
     crypto::SymmetricKey::HMAC_SHA1,
@@ -143,83 +139,78 @@
   },
 #endif
 
-  // These tests come from RFC 3962, via BSD source code at
-  // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "ATHENA.MIT.EDUraeburn",
-    1,
-    160,
-    "cdedb5281bb2f801565a1122b25635150ad1f7a0",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "ATHENA.MIT.EDUraeburn",
-    2,
-    160,
-    "01dbee7f4a9e243e988b62c73cda935da05378b9",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "ATHENA.MIT.EDUraeburn",
-    1200,
-    160,
-    "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "password",
-    "\0224VxxV4\022", /* 0x1234567878563412 */
-    5,
-    160,
-    "d1daa78615f287e6a1c8b120d7062a493f98d203",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
-    "pass phrase equals block size",
-    1200,
-    160,
-    "139c30c0966bc32ba55fdbf212530ac9c5ec59f1",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
-    "pass phrase exceeds block size",
-    1200,
-    160,
-    "9ccad6d468770cd51b10e6a68721be611a8b4d28",
-  },
-  {
-    crypto::SymmetricKey::HMAC_SHA1,
-    "\360\235\204\236", /* g-clef (0xf09d849e) */
-    "EXAMPLE.COMpianist",
-    50,
-    160,
-    "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0",
-  },
+    // These tests come from RFC 3962, via BSD source code at
+    // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain.
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn", 1,
+        160, "cdedb5281bb2f801565a1122b25635150ad1f7a0",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn", 2,
+        160, "01dbee7f4a9e243e988b62c73cda935da05378b9",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn",
+        1200, 160, "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1, "password",
+        "\022"
+        "4VxxV4\022", /* 0x1234567878563412 */
+        5, 160, "d1daa78615f287e6a1c8b120d7062a493f98d203",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase equals block size", 1200, 160,
+        "139c30c0966bc32ba55fdbf212530ac9c5ec59f1",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size", 1200, 160,
+        "9ccad6d468770cd51b10e6a68721be611a8b4d28",
+    },
+    {
+        crypto::SymmetricKey::HMAC_SHA1,
+        "\360\235\204\236", /* g-clef (0xf09d849e) */
+        "EXAMPLE.COMpianist", 50, 160,
+        "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0",
+    },
 
-  // Regression tests for AES keys, derived from the Linux NSS implementation.
-  {
-    crypto::SymmetricKey::AES,
-    "A test password",
-    "saltsalt",
-    1,
-    256,
-    "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de",
-  },
-  {
-    crypto::SymmetricKey::AES,
-    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
-    "pass phrase exceeds block size",
-    20,
-    256,
-    "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c",
-  },
+    // Regression tests for AES keys, derived from the Linux NSS implementation.
+    {
+        crypto::SymmetricKey::AES, "A test password", "saltsalt", 1, 256,
+        "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de",
+    },
+    {
+        crypto::SymmetricKey::AES,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size", 20, 256,
+        "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c",
+    },
 };
 
-INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest,
-                        testing::ValuesIn(kTestVectors));
+static const ScryptTestVector kTestVectorsScrypt[] = {
+    // From RFC 7914, "The scrypt Password-Based Key Derivation Function",
+    // https://tools.ietf.org/html/rfc7914.html. The fourth test vector is
+    // intentionally not used, as it would make the test significantly slower,
+    // due to the very high cost parameter.
+    {crypto::SymmetricKey::HMAC_SHA1, "", "", 16, 1, 1, 512,
+     "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069de"
+     "d0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906"},
+    {crypto::SymmetricKey::HMAC_SHA1, "password", "NaCl", 1024, 8, 16, 512,
+     "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92"
+     "e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"},
+    {crypto::SymmetricKey::HMAC_SHA1, "pleaseletmein", "SodiumChloride", 16384,
+     8, 1, 512,
+     "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d54329556"
+     "13f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887"}};
+
+INSTANTIATE_TEST_CASE_P(,
+                        SymmetricKeyDeriveKeyFromPasswordUsingPbkdf2Test,
+                        testing::ValuesIn(kTestVectorsPbkdf2));
+
+INSTANTIATE_TEST_CASE_P(,
+                        SymmetricKeyDeriveKeyFromPasswordUsingScryptTest,
+                        testing::ValuesIn(kTestVectorsScrypt));
diff --git a/src/crypto/third_party/nss/LICENSE b/src/crypto/third_party/nss/LICENSE
deleted file mode 100644
index 0367164..0000000
--- a/src/crypto/third_party/nss/LICENSE
+++ /dev/null
@@ -1,35 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
diff --git a/src/crypto/third_party/nss/README.chromium b/src/crypto/third_party/nss/README.chromium
deleted file mode 100644
index f0bb87b..0000000
--- a/src/crypto/third_party/nss/README.chromium
+++ /dev/null
@@ -1,14 +0,0 @@
-Name: Network Security Services (NSS)
-URL: http://www.mozilla.org/projects/security/pki/nss/
-License: MPL 1.1/GPL 2.0/LGPL 2.1
-
-We extracted the SHA-256 source files, eliminated unneeded dependencies,
-deleted or commented out unused code, and tweaked them for Chrome's source
-tree.  sha512.c is renamed sha512.cc so that it can include Chrome's C++
-header "base/basictypes.h".  We define NOUNROLL256 to reduce the object code
-size.
-
-In blapi.h and sha512.cc, replaced uint32 by unsigned int so that they can
-be compiled with -DNO_NSPR_10_SUPPORT.  NO_NSPR_10_SUPPORT turns off the
-definition of the NSPR 1.0 types int8 - int64 and uint8 - uint64 to avoid
-conflict with the same-named types defined in "base/basictypes.h".
diff --git a/src/crypto/third_party/nss/chromium-blapi.h b/src/crypto/third_party/nss/chromium-blapi.h
deleted file mode 100644
index 2ca772e..0000000
--- a/src/crypto/third_party/nss/chromium-blapi.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * crypto.h - public data structures and prototypes for the crypto library
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* $Id: blapi.h,v 1.27 2007/11/09 18:49:32 wtc%google.com Exp $ */
-
-#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_
-#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_
-
-#include "crypto/third_party/nss/chromium-blapit.h"
-
-/******************************************/
-
-extern SHA256Context *SHA256_NewContext(void);
-extern void SHA256_DestroyContext(SHA256Context *cx, PRBool freeit);
-extern void SHA256_Begin(SHA256Context *cx);
-extern void SHA256_Update(SHA256Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA256_End(SHA256Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src,
-			      unsigned int src_length);
-extern SECStatus SHA256_Hash(unsigned char *dest, const char *src);
-extern void SHA256_TraceState(SHA256Context *cx);
-extern unsigned int SHA256_FlattenSize(SHA256Context *cx);
-extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space);
-extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg);
-extern void SHA256_Clone(SHA256Context *dest, SHA256Context *src);
-
-/******************************************/
-
-extern SHA512Context *SHA512_NewContext(void);
-extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit);
-extern void SHA512_Begin(SHA512Context *cx);
-extern void SHA512_Update(SHA512Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA512_End(SHA512Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src,
-			      unsigned int src_length);
-extern SECStatus SHA512_Hash(unsigned char *dest, const char *src);
-extern void SHA512_TraceState(SHA512Context *cx);
-extern unsigned int SHA512_FlattenSize(SHA512Context *cx);
-extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space);
-extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg);
-extern void SHA512_Clone(SHA512Context *dest, SHA512Context *src);
-
-/******************************************/
-
-extern SHA384Context *SHA384_NewContext(void);
-extern void SHA384_DestroyContext(SHA384Context *cx, PRBool freeit);
-extern void SHA384_Begin(SHA384Context *cx);
-extern void SHA384_Update(SHA384Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA384_End(SHA384Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src,
-			      unsigned int src_length);
-extern SECStatus SHA384_Hash(unsigned char *dest, const char *src);
-extern void SHA384_TraceState(SHA384Context *cx);
-extern unsigned int SHA384_FlattenSize(SHA384Context *cx);
-extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space);
-extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg);
-extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src);
-
-#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ */
diff --git a/src/crypto/third_party/nss/chromium-blapit.h b/src/crypto/third_party/nss/chromium-blapit.h
deleted file mode 100644
index 669f64d..0000000
--- a/src/crypto/third_party/nss/chromium-blapit.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * blapit.h - public data structures for the crypto library
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dr Vipul Gupta <vipul.gupta@sun.com> and
- *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* $Id: blapit.h,v 1.20 2007/02/28 19:47:37 rrelyea%redhat.com Exp $ */
-
-#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
-#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
-
-#include "base/third_party/nspr/prtypes.h"
-
-/*
-** A status code. Status's are used by procedures that return status
-** values. Again the motivation is so that a compiler can generate
-** warnings when return values are wrong. Correct testing of status codes:
-**
-**      SECStatus rv;
-**      rv = some_function (some_argument);
-**      if (rv != SECSuccess)
-**              do_an_error_thing();
-**
-*/
-typedef enum _SECStatus {
-    SECWouldBlock = -2,
-    SECFailure = -1,
-    SECSuccess = 0
-} SECStatus;
-
-#define SHA256_LENGTH 		32 	/* bytes */
-#define SHA384_LENGTH 		48 	/* bytes */
-#define SHA512_LENGTH 		64 	/* bytes */
-#define HASH_LENGTH_MAX         SHA512_LENGTH
-
-/*
- * Input block size for each hash algorithm.
- */
-
-#define SHA256_BLOCK_LENGTH      64     /* bytes */
-#define SHA384_BLOCK_LENGTH     128     /* bytes */
-#define SHA512_BLOCK_LENGTH     128     /* bytes */
-#define HASH_BLOCK_LENGTH_MAX   SHA512_BLOCK_LENGTH
-
-/***************************************************************************
-** Opaque objects
-*/
-
-struct SHA256ContextStr     ;
-struct SHA512ContextStr     ;
-
-typedef struct SHA256ContextStr     SHA256Context;
-typedef struct SHA512ContextStr     SHA512Context;
-/* SHA384Context is really a SHA512ContextStr.  This is not a mistake. */
-typedef struct SHA512ContextStr     SHA384Context;
-
-#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ */
diff --git a/src/crypto/third_party/nss/chromium-nss.h b/src/crypto/third_party/nss/chromium-nss.h
deleted file mode 100644
index 5ef28e3..0000000
--- a/src/crypto/third_party/nss/chromium-nss.h
+++ /dev/null
@@ -1,70 +0,0 @@
- /* ***** BEGIN LICENSE BLOCK *****
-  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-  *
-  * The contents of this file are subject to the Mozilla Public License Version
-  * 1.1 (the "License"); you may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at
-  * http://www.mozilla.org/MPL/
-  *
-  * Software distributed under the License is distributed on an "AS IS" basis,
-  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-  * for the specific language governing rights and limitations under the
-  * License.
-  *
-  * The Original Code is the Netscape security libraries.
-  *
-  * The Initial Developer of the Original Code is
-  * Netscape Communications Corporation.
-  * Portions created by the Initial Developer are Copyright (C) 1994-2000
-  * the Initial Developer. All Rights Reserved.
-  *
-  * Contributor(s):
-  *
-  * Alternatively, the contents of this file may be used under the terms of
-  * either the GNU General Public License Version 2 or later (the "GPL"), or
-  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-  * in which case the provisions of the GPL or the LGPL are applicable instead
-  * of those above. If you wish to allow use of your version of this file only
-  * under the terms of either the GPL or the LGPL, and not to allow others to
-  * use your version of this file under the terms of the MPL, indicate your
-  * decision by deleting the provisions above and replace them with the notice
-  * and other provisions required by the GPL or the LGPL. If you do not delete
-  * the provisions above, a recipient may use your version of this file under
-  * the terms of any one of the MPL, the GPL or the LGPL.
-  *
-  * ***** END LICENSE BLOCK ***** */
-
-#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
-#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
-
-// This file contains some functions we borrowed from NSS.
-
-#include <keyhi.h>
-#include <secmod.h>
-
-#include "crypto/crypto_export.h"
-
-// Like PK11_ImportEncryptedPrivateKeyInfo, but hardcoded for EC, and returns
-// the SECKEYPrivateKey.
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=211546
-// When we use NSS 3.13.2 or later,
-// PK11_ImportEncryptedPrivateKeyInfoAndReturnKey can be used instead.
-SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey(
-    PK11SlotInfo* slot,
-    SECKEYEncryptedPrivateKeyInfo* epki,
-    SECItem* password,
-    SECItem* nickname,
-    SECItem* public_value,
-    PRBool permanent,
-    PRBool sensitive,
-    SECKEYPrivateKey** private_key,
-    void* wincx);
-
-// Like SEC_DerSignData.
-CRYPTO_EXPORT SECStatus DerSignData(PLArenaPool *arena,
-                                    SECItem *result,
-                                    SECItem *input,
-                                    SECKEYPrivateKey *key,
-                                    SECOidTag algo_id);
-
-#endif  // CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
diff --git a/src/crypto/third_party/nss/chromium-sha256.h b/src/crypto/third_party/nss/chromium-sha256.h
deleted file mode 100644
index 14661dc..0000000
--- a/src/crypto/third_party/nss/chromium-sha256.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
-#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
-
-#include "base/third_party/nspr/prtypes.h"
-
-struct SHA256ContextStr {
-    union {
-	PRUint32 w[64];	    /* message schedule, input buffer, plus 48 words */
-	PRUint8  b[256];
-    } u;
-    PRUint32 h[8];		/* 8 state variables */
-    PRUint32 sizeHi,sizeLo;	/* 64-bit count of hashed bytes. */
-};
-
-#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ */
diff --git a/src/crypto/third_party/nss/pk11akey.cc b/src/crypto/third_party/nss/pk11akey.cc
deleted file mode 100644
index 4db582f..0000000
--- a/src/crypto/third_party/nss/pk11akey.cc
+++ /dev/null
@@ -1,98 +0,0 @@
- /* ***** BEGIN LICENSE BLOCK *****
-  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-  *
-  * The contents of this file are subject to the Mozilla Public License Version
-  * 1.1 (the "License"); you may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at
-  * http://www.mozilla.org/MPL/
-  *
-  * Software distributed under the License is distributed on an "AS IS" basis,
-  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-  * for the specific language governing rights and limitations under the
-  * License.
-  *
-  * The Original Code is the Netscape security libraries.
-  *
-  * The Initial Developer of the Original Code is
-  * Netscape Communications Corporation.
-  * Portions created by the Initial Developer are Copyright (C) 1994-2000
-  * the Initial Developer. All Rights Reserved.
-  *
-  * Contributor(s):
-  *   Dr Stephen Henson <stephen.henson@gemplus.com>
-  *   Dr Vipul Gupta <vipul.gupta@sun.com>, and
-  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
-  *
-  * Alternatively, the contents of this file may be used under the terms of
-  * either the GNU General Public License Version 2 or later (the "GPL"), or
-  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-  * in which case the provisions of the GPL or the LGPL are applicable instead
-  * of those above. If you wish to allow use of your version of this file only
-  * under the terms of either the GPL or the LGPL, and not to allow others to
-  * use your version of this file under the terms of the MPL, indicate your
-  * decision by deleting the provisions above and replace them with the notice
-  * and other provisions required by the GPL or the LGPL. If you do not delete
-  * the provisions above, a recipient may use your version of this file under
-  * the terms of any one of the MPL, the GPL or the LGPL.
-  *
-  * ***** END LICENSE BLOCK ***** */
-
-#include "crypto/third_party/nss/chromium-nss.h"
-
-#include <pk11pub.h>
-
-#include "base/logging.h"
-
-// Based on PK11_ImportEncryptedPrivateKeyInfo function in
-// mozilla/security/nss/lib/pk11wrap/pk11akey.c.
-SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey(
-    PK11SlotInfo* slot,
-    SECKEYEncryptedPrivateKeyInfo* epki,
-    SECItem* password,
-    SECItem* nickname,
-    SECItem* public_value,
-    PRBool permanent,
-    PRBool sensitive,
-    SECKEYPrivateKey** private_key,
-    void* wincx) {
-  SECItem* crypto_param = NULL;
-
-  CK_ATTRIBUTE_TYPE usage = CKA_SIGN;
-
-  PK11SymKey* key = PK11_PBEKeyGen(slot,
-                                   &epki->algorithm,
-                                   password,
-                                   PR_FALSE,  // faulty3DES
-                                   wincx);
-  if (key == NULL) {
-    DLOG(ERROR) << "PK11_PBEKeyGen: " << PORT_GetError();
-    return SECFailure;
-  }
-
-  CK_MECHANISM_TYPE crypto_mech_type = PK11_GetPBECryptoMechanism(
-      &epki->algorithm, &crypto_param, password);
-  if (crypto_mech_type == CKM_INVALID_MECHANISM) {
-    DLOG(ERROR) << "PK11_GetPBECryptoMechanism: " << PORT_GetError();
-    PK11_FreeSymKey(key);
-    return SECFailure;
-  }
-
-  crypto_mech_type = PK11_GetPadMechanism(crypto_mech_type);
-
-  *private_key = PK11_UnwrapPrivKey(slot, key, crypto_mech_type, crypto_param,
-                                    &epki->encryptedData, nickname,
-                                    public_value, permanent, sensitive, CKK_EC,
-                                    &usage, 1, wincx);
-
-  if (crypto_param != NULL)
-    SECITEM_ZfreeItem(crypto_param, PR_TRUE);
-
-  PK11_FreeSymKey(key);
-
-  if (!*private_key) {
-    DLOG(ERROR) << "PK11_UnwrapPrivKey: " << PORT_GetError();
-    return SECFailure;
-  }
-
-  return SECSuccess;
-}
diff --git a/src/crypto/third_party/nss/secsign.cc b/src/crypto/third_party/nss/secsign.cc
deleted file mode 100644
index a788def..0000000
--- a/src/crypto/third_party/nss/secsign.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Signature stuff.
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "crypto/third_party/nss/chromium-nss.h"
-
-#include <vector>
-
-#include <cryptohi.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-
-SECStatus DerSignData(PLArenaPool *arena,
-                      SECItem *result,
-                      SECItem *input,
-                      SECKEYPrivateKey *key,
-                      SECOidTag algo_id) {
-  if (key->keyType != ecKey) {
-    return SEC_DerSignData(arena, result, input->data, input->len, key,
-                           algo_id);
-  }
-
-  // NSS has a private function sec_DecodeSigAlg it uses to figure out the
-  // correct hash from the algorithm id.
-  HASH_HashType hash_type;
-  switch (algo_id) {
-    case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
-      hash_type = HASH_AlgSHA1;
-      break;
-#ifdef SHA224_LENGTH
-    case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
-      hash_type = HASH_AlgSHA224;
-      break;
-#endif
-    case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
-      hash_type = HASH_AlgSHA256;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
-      hash_type = HASH_AlgSHA384;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
-      hash_type = HASH_AlgSHA512;
-      break;
-    default:
-      PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-      return SECFailure;
-  }
-
-  // Hash the input.
-  std::vector<uint8> hash_data(HASH_ResultLen(hash_type));
-  SECStatus rv = HASH_HashBuf(
-      hash_type, &hash_data[0], input->data, input->len);
-  if (rv != SECSuccess)
-    return rv;
-  SECItem hash = {siBuffer, &hash_data[0], 
-		  static_cast<unsigned int>(hash_data.size())};
-
-  // Compute signature of hash.
-  int signature_len = PK11_SignatureLen(key);
-  std::vector<uint8> signature_data(signature_len);
-  SECItem sig = {siBuffer, &signature_data[0], 
-		 static_cast<unsigned int>(signature_len)};
-  rv = PK11_Sign(key, &sig, &hash);
-  if (rv != SECSuccess)
-    return rv;
-
-  CERTSignedData sd;
-  PORT_Memset(&sd, 0, sizeof(sd));
-  // Fill in tbsCertificate.
-  sd.data.data = (unsigned char*) input->data;
-  sd.data.len = input->len;
-
-  // Fill in signatureAlgorithm.
-  rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algo_id, 0);
-  if (rv != SECSuccess)
-    return rv;
-
-  // Fill in signatureValue.
-  rv = DSAU_EncodeDerSigWithLen(&sd.signature, &sig, sig.len);
-  if (rv != SECSuccess)
-    return rv;
-  sd.signature.len <<=  3;  // Convert to bit string.
-
-  // DER encode the signed data object.
-  void* encode_result = SEC_ASN1EncodeItem(
-      arena, result, &sd, SEC_ASN1_GET(CERT_SignedDataTemplate));
-
-  PORT_Free(sd.signature.data);
-
-  return encode_result ? SECSuccess : SECFailure;
-}
diff --git a/src/crypto/third_party/nss/sha512.cc b/src/crypto/third_party/nss/sha512.cc
deleted file mode 100644
index 976a604..0000000
--- a/src/crypto/third_party/nss/sha512.cc
+++ /dev/null
@@ -1,1391 +0,0 @@
-/*
- * sha512.c - implementation of SHA256, SHA384 and SHA512
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* $Id: sha512.c,v 1.9 2006/10/13 16:54:04 wtchang%redhat.com Exp $ */
-
-// Prevent manual unrolling in the sha256 code, which reduces the binary code
-// size from ~10k to ~1k.  The performance should be reasonable for our use.
-#define NOUNROLL256 1
-
-#include "base/third_party/nspr/prtypes.h"  /* for PRUintXX */
-#if defined(_X86_) || defined(SHA_NO_LONG_LONG)
-#define NOUNROLL512 1
-#undef HAVE_LONG_LONG
-#endif
-#include "crypto/third_party/nss/chromium-blapi.h"
-#include "crypto/third_party/nss/chromium-sha256.h"    /* for struct SHA256ContextStr */
-
-#include <stdlib.h>
-#include <string.h>
-#define PORT_New(type) static_cast<type*>(malloc(sizeof(type)))
-#define PORT_ZFree(ptr, len) do { memset(ptr, 0, len); free(ptr); } while (0)
-#define PORT_Strlen(s) static_cast<unsigned int>(strlen(s))
-#define PORT_Memcpy memcpy
-
-/* ============= Common constants and defines ======================= */
-
-#define W ctx->u.w
-#define B ctx->u.b
-#define H ctx->h
-
-#define SHR(x,n) (x >> n)
-#define SHL(x,n) (x << n)
-#define Ch(x,y,z)  ((x & y) ^ (~x & z))
-#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
-
-/* Padding used with all flavors of SHA */
-static const PRUint8 pad[240] = {
-0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-   /* compiler will fill the rest in with zeros */
-};
-
-/* ============= SHA256 implemenmtation ================================== */
-
-/* SHA-256 constants, K256. */
-static const PRUint32 K256[64] = {
-    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
-    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
-    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
-    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
-    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
-    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
-    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
-    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
-    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-/* SHA-256 initial hash values */
-static const PRUint32 H256[8] = {
-    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
-    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
-};
-
-#if defined(_MSC_VER) && defined(_X86_)
-#ifndef FORCEINLINE
-#if (_MSC_VER >= 1200)
-#define FORCEINLINE __forceinline
-#else
-#define FORCEINLINE __inline
-#endif
-#endif
-#define FASTCALL __fastcall
-
-static FORCEINLINE PRUint32 FASTCALL
-swap4b(PRUint32 dwd)
-{
-    __asm {
-    	mov   eax,dwd
-	bswap eax
-    }
-}
-
-#define SHA_HTONL(x) swap4b(x)
-#define BYTESWAP4(x)  x = SHA_HTONL(x)
-
-#elif defined(LINUX) && defined(_X86_)
-#undef  __OPTIMIZE__
-#define __OPTIMIZE__ 1
-#undef  __pentium__
-#define __pentium__ 1
-#include <byteswap.h>
-#define SHA_HTONL(x) bswap_32(x)
-#define BYTESWAP4(x)  x = SHA_HTONL(x)
-
-#else /* neither windows nor Linux PC */
-#define SWAP4MASK  0x00FF00FF
-#define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \
-                      ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK))
-#define BYTESWAP4(x)  x = SHA_HTONL(x)
-#endif
-
-#if defined(_MSC_VER) && defined(_X86_)
-#pragma intrinsic (_lrotr, _lrotl)
-#define ROTR32(x,n) _lrotr(x,n)
-#define ROTL32(x,n) _lrotl(x,n)
-#else
-#define ROTR32(x,n) ((x >> n) | (x << ((8 * sizeof x) - n)))
-#define ROTL32(x,n) ((x << n) | (x >> ((8 * sizeof x) - n)))
-#endif
-
-/* Capitol Sigma and lower case sigma functions */
-#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22))
-#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25))
-#define s0(x) (t1 = x, ROTR32(t1, 7) ^ ROTR32(t1,18) ^ SHR(t1, 3))
-#define s1(x) (t2 = x, ROTR32(t2,17) ^ ROTR32(t2,19) ^ SHR(t2,10))
-
-SHA256Context *
-SHA256_NewContext(void)
-{
-    SHA256Context *ctx = PORT_New(SHA256Context);
-    return ctx;
-}
-
-void
-SHA256_DestroyContext(SHA256Context *ctx, PRBool freeit)
-{
-    if (freeit) {
-        PORT_ZFree(ctx, sizeof *ctx);
-    }
-}
-
-void
-SHA256_Begin(SHA256Context *ctx)
-{
-    memset(ctx, 0, sizeof *ctx);
-    memcpy(H, H256, sizeof H256);
-}
-
-static void
-SHA256_Compress(SHA256Context *ctx)
-{
-  {
-    register PRUint32 t1, t2;
-
-#if defined(IS_LITTLE_ENDIAN)
-    BYTESWAP4(W[0]);
-    BYTESWAP4(W[1]);
-    BYTESWAP4(W[2]);
-    BYTESWAP4(W[3]);
-    BYTESWAP4(W[4]);
-    BYTESWAP4(W[5]);
-    BYTESWAP4(W[6]);
-    BYTESWAP4(W[7]);
-    BYTESWAP4(W[8]);
-    BYTESWAP4(W[9]);
-    BYTESWAP4(W[10]);
-    BYTESWAP4(W[11]);
-    BYTESWAP4(W[12]);
-    BYTESWAP4(W[13]);
-    BYTESWAP4(W[14]);
-    BYTESWAP4(W[15]);
-#endif
-
-#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16])
-
-    /* prepare the "message schedule"   */
-#ifdef NOUNROLL256
-    {
-	int t;
-	for (t = 16; t < 64; ++t) {
-	    INITW(t);
-	}
-    }
-#else
-    INITW(16);
-    INITW(17);
-    INITW(18);
-    INITW(19);
-
-    INITW(20);
-    INITW(21);
-    INITW(22);
-    INITW(23);
-    INITW(24);
-    INITW(25);
-    INITW(26);
-    INITW(27);
-    INITW(28);
-    INITW(29);
-
-    INITW(30);
-    INITW(31);
-    INITW(32);
-    INITW(33);
-    INITW(34);
-    INITW(35);
-    INITW(36);
-    INITW(37);
-    INITW(38);
-    INITW(39);
-
-    INITW(40);
-    INITW(41);
-    INITW(42);
-    INITW(43);
-    INITW(44);
-    INITW(45);
-    INITW(46);
-    INITW(47);
-    INITW(48);
-    INITW(49);
-
-    INITW(50);
-    INITW(51);
-    INITW(52);
-    INITW(53);
-    INITW(54);
-    INITW(55);
-    INITW(56);
-    INITW(57);
-    INITW(58);
-    INITW(59);
-
-    INITW(60);
-    INITW(61);
-    INITW(62);
-    INITW(63);
-
-#endif
-#undef INITW
-  }
-  {
-    PRUint32 a, b, c, d, e, f, g, h;
-
-    a = H[0];
-    b = H[1];
-    c = H[2];
-    d = H[3];
-    e = H[4];
-    f = H[5];
-    g = H[6];
-    h = H[7];
-
-#define ROUND(n,a,b,c,d,e,f,g,h) \
-    h += S1(e) + Ch(e,f,g) + K256[n] + W[n]; \
-    d += h; \
-    h += S0(a) + Maj(a,b,c);
-
-#ifdef NOUNROLL256
-    {
-	int t;
-	for (t = 0; t < 64; t+= 8) {
-	    ROUND(t+0,a,b,c,d,e,f,g,h)
-	    ROUND(t+1,h,a,b,c,d,e,f,g)
-	    ROUND(t+2,g,h,a,b,c,d,e,f)
-	    ROUND(t+3,f,g,h,a,b,c,d,e)
-	    ROUND(t+4,e,f,g,h,a,b,c,d)
-	    ROUND(t+5,d,e,f,g,h,a,b,c)
-	    ROUND(t+6,c,d,e,f,g,h,a,b)
-	    ROUND(t+7,b,c,d,e,f,g,h,a)
-	}
-    }
-#else
-    ROUND( 0,a,b,c,d,e,f,g,h)
-    ROUND( 1,h,a,b,c,d,e,f,g)
-    ROUND( 2,g,h,a,b,c,d,e,f)
-    ROUND( 3,f,g,h,a,b,c,d,e)
-    ROUND( 4,e,f,g,h,a,b,c,d)
-    ROUND( 5,d,e,f,g,h,a,b,c)
-    ROUND( 6,c,d,e,f,g,h,a,b)
-    ROUND( 7,b,c,d,e,f,g,h,a)
-
-    ROUND( 8,a,b,c,d,e,f,g,h)
-    ROUND( 9,h,a,b,c,d,e,f,g)
-    ROUND(10,g,h,a,b,c,d,e,f)
-    ROUND(11,f,g,h,a,b,c,d,e)
-    ROUND(12,e,f,g,h,a,b,c,d)
-    ROUND(13,d,e,f,g,h,a,b,c)
-    ROUND(14,c,d,e,f,g,h,a,b)
-    ROUND(15,b,c,d,e,f,g,h,a)
-
-    ROUND(16,a,b,c,d,e,f,g,h)
-    ROUND(17,h,a,b,c,d,e,f,g)
-    ROUND(18,g,h,a,b,c,d,e,f)
-    ROUND(19,f,g,h,a,b,c,d,e)
-    ROUND(20,e,f,g,h,a,b,c,d)
-    ROUND(21,d,e,f,g,h,a,b,c)
-    ROUND(22,c,d,e,f,g,h,a,b)
-    ROUND(23,b,c,d,e,f,g,h,a)
-
-    ROUND(24,a,b,c,d,e,f,g,h)
-    ROUND(25,h,a,b,c,d,e,f,g)
-    ROUND(26,g,h,a,b,c,d,e,f)
-    ROUND(27,f,g,h,a,b,c,d,e)
-    ROUND(28,e,f,g,h,a,b,c,d)
-    ROUND(29,d,e,f,g,h,a,b,c)
-    ROUND(30,c,d,e,f,g,h,a,b)
-    ROUND(31,b,c,d,e,f,g,h,a)
-
-    ROUND(32,a,b,c,d,e,f,g,h)
-    ROUND(33,h,a,b,c,d,e,f,g)
-    ROUND(34,g,h,a,b,c,d,e,f)
-    ROUND(35,f,g,h,a,b,c,d,e)
-    ROUND(36,e,f,g,h,a,b,c,d)
-    ROUND(37,d,e,f,g,h,a,b,c)
-    ROUND(38,c,d,e,f,g,h,a,b)
-    ROUND(39,b,c,d,e,f,g,h,a)
-
-    ROUND(40,a,b,c,d,e,f,g,h)
-    ROUND(41,h,a,b,c,d,e,f,g)
-    ROUND(42,g,h,a,b,c,d,e,f)
-    ROUND(43,f,g,h,a,b,c,d,e)
-    ROUND(44,e,f,g,h,a,b,c,d)
-    ROUND(45,d,e,f,g,h,a,b,c)
-    ROUND(46,c,d,e,f,g,h,a,b)
-    ROUND(47,b,c,d,e,f,g,h,a)
-
-    ROUND(48,a,b,c,d,e,f,g,h)
-    ROUND(49,h,a,b,c,d,e,f,g)
-    ROUND(50,g,h,a,b,c,d,e,f)
-    ROUND(51,f,g,h,a,b,c,d,e)
-    ROUND(52,e,f,g,h,a,b,c,d)
-    ROUND(53,d,e,f,g,h,a,b,c)
-    ROUND(54,c,d,e,f,g,h,a,b)
-    ROUND(55,b,c,d,e,f,g,h,a)
-
-    ROUND(56,a,b,c,d,e,f,g,h)
-    ROUND(57,h,a,b,c,d,e,f,g)
-    ROUND(58,g,h,a,b,c,d,e,f)
-    ROUND(59,f,g,h,a,b,c,d,e)
-    ROUND(60,e,f,g,h,a,b,c,d)
-    ROUND(61,d,e,f,g,h,a,b,c)
-    ROUND(62,c,d,e,f,g,h,a,b)
-    ROUND(63,b,c,d,e,f,g,h,a)
-#endif
-
-    H[0] += a;
-    H[1] += b;
-    H[2] += c;
-    H[3] += d;
-    H[4] += e;
-    H[5] += f;
-    H[6] += g;
-    H[7] += h;
-  }
-#undef ROUND
-}
-
-#undef s0
-#undef s1
-#undef S0
-#undef S1
-
-void
-SHA256_Update(SHA256Context *ctx, const unsigned char *input,
-		    unsigned int inputLen)
-{
-    unsigned int inBuf = ctx->sizeLo & 0x3f;
-    if (!inputLen)
-    	return;
-
-    /* Add inputLen into the count of bytes processed, before processing */
-    if ((ctx->sizeLo += inputLen) < inputLen)
-    	ctx->sizeHi++;
-
-    /* if data already in buffer, attemp to fill rest of buffer */
-    if (inBuf) {
-    	unsigned int todo = SHA256_BLOCK_LENGTH - inBuf;
-	if (inputLen < todo)
-	    todo = inputLen;
-	memcpy(B + inBuf, input, todo);
-	input    += todo;
-	inputLen -= todo;
-	if (inBuf + todo == SHA256_BLOCK_LENGTH)
-	    SHA256_Compress(ctx);
-    }
-
-    /* if enough data to fill one or more whole buffers, process them. */
-    while (inputLen >= SHA256_BLOCK_LENGTH) {
-    	memcpy(B, input, SHA256_BLOCK_LENGTH);
-	input    += SHA256_BLOCK_LENGTH;
-	inputLen -= SHA256_BLOCK_LENGTH;
-	SHA256_Compress(ctx);
-    }
-    /* if data left over, fill it into buffer */
-    if (inputLen)
-    	memcpy(B, input, inputLen);
-}
-
-void
-SHA256_End(SHA256Context *ctx, unsigned char *digest,
-           unsigned int *digestLen, unsigned int maxDigestLen)
-{
-    unsigned int inBuf = ctx->sizeLo & 0x3f;
-    unsigned int padLen = (inBuf < 56) ? (56 - inBuf) : (56 + 64 - inBuf);
-    PRUint32 hi, lo;
-#ifdef SWAP4MASK
-    PRUint32 t1;
-#endif
-
-    hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29);
-    lo = (ctx->sizeLo << 3);
-
-    SHA256_Update(ctx, pad, padLen);
-
-#if defined(IS_LITTLE_ENDIAN)
-    W[14] = SHA_HTONL(hi);
-    W[15] = SHA_HTONL(lo);
-#else
-    W[14] = hi;
-    W[15] = lo;
-#endif
-    SHA256_Compress(ctx);
-
-    /* now output the answer */
-#if defined(IS_LITTLE_ENDIAN)
-    BYTESWAP4(H[0]);
-    BYTESWAP4(H[1]);
-    BYTESWAP4(H[2]);
-    BYTESWAP4(H[3]);
-    BYTESWAP4(H[4]);
-    BYTESWAP4(H[5]);
-    BYTESWAP4(H[6]);
-    BYTESWAP4(H[7]);
-#endif
-    padLen = PR_MIN(SHA256_LENGTH, maxDigestLen);
-    memcpy(digest, H, padLen);
-    if (digestLen)
-	*digestLen = padLen;
-}
-
-/* Comment out unused code, mostly the SHA384 and SHA512 implementations. */
-#if 0
-SECStatus
-SHA256_HashBuf(unsigned char *dest, const unsigned char *src,
-               unsigned int src_length)
-{
-    SHA256Context ctx;
-    unsigned int outLen;
-
-    SHA256_Begin(&ctx);
-    SHA256_Update(&ctx, src, src_length);
-    SHA256_End(&ctx, dest, &outLen, SHA256_LENGTH);
-
-    return SECSuccess;
-}
-
-
-SECStatus
-SHA256_Hash(unsigned char *dest, const char *src)
-{
-    return SHA256_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
-}
-
-
-void SHA256_TraceState(SHA256Context *ctx) { }
-
-unsigned int
-SHA256_FlattenSize(SHA256Context *ctx)
-{
-    return sizeof *ctx;
-}
-
-SECStatus
-SHA256_Flatten(SHA256Context *ctx,unsigned char *space)
-{
-    PORT_Memcpy(space, ctx, sizeof *ctx);
-    return SECSuccess;
-}
-
-SHA256Context *
-SHA256_Resurrect(unsigned char *space, void *arg)
-{
-    SHA256Context *ctx = SHA256_NewContext();
-    if (ctx)
-	PORT_Memcpy(ctx, space, sizeof *ctx);
-    return ctx;
-}
-
-void SHA256_Clone(SHA256Context *dest, SHA256Context *src)
-{
-    memcpy(dest, src, sizeof *dest);
-}
-
-
-/* ======= SHA512 and SHA384 common constants and defines ================= */
-
-/* common #defines for SHA512 and SHA384 */
-#if defined(HAVE_LONG_LONG)
-#define ROTR64(x,n) ((x >> n) | (x << (64 - n)))
-#define ROTL64(x,n) ((x << n) | (x >> (64 - n)))
-
-#define S0(x) (ROTR64(x,28) ^ ROTR64(x,34) ^ ROTR64(x,39))
-#define S1(x) (ROTR64(x,14) ^ ROTR64(x,18) ^ ROTR64(x,41))
-#define s0(x) (t1 = x, ROTR64(t1, 1) ^ ROTR64(t1, 8) ^ SHR(t1,7))
-#define s1(x) (t2 = x, ROTR64(t2,19) ^ ROTR64(t2,61) ^ SHR(t2,6))
-
-#if PR_BYTES_PER_LONG == 8
-#define ULLC(hi,lo) 0x ## hi ## lo ## UL
-#elif defined(_MSC_VER)
-#define ULLC(hi,lo) 0x ## hi ## lo ## ui64
-#else
-#define ULLC(hi,lo) 0x ## hi ## lo ## ULL
-#endif
-
-#define SHA_MASK16 ULLC(0000FFFF,0000FFFF)
-#define SHA_MASK8  ULLC(00FF00FF,00FF00FF)
-#define SHA_HTONLL(x) (t1 = x, \
-  t1 = ((t1 & SHA_MASK8 ) <<  8) | ((t1 >>  8) & SHA_MASK8 ), \
-  t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16), \
-  (t1 >> 32) | (t1 << 32))
-#define BYTESWAP8(x)  x = SHA_HTONLL(x)
-
-#else /* no long long */
-
-#if defined(IS_LITTLE_ENDIAN)
-#define ULLC(hi,lo) { 0x ## lo ## U, 0x ## hi ## U }
-#else
-#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U }
-#endif
-
-#define SHA_HTONLL(x) ( BYTESWAP4(x.lo), BYTESWAP4(x.hi), \
-   x.hi ^= x.lo ^= x.hi ^= x.lo, x)
-#define BYTESWAP8(x)  do { PRUint32 tmp; BYTESWAP4(x.lo); BYTESWAP4(x.hi); \
-   tmp = x.lo; x.lo = x.hi; x.hi = tmp; } while (0)
-#endif
-
-/* SHA-384 and SHA-512 constants, K512. */
-static const PRUint64 K512[80] = {
-#if PR_BYTES_PER_LONG == 8
-     0x428a2f98d728ae22UL ,  0x7137449123ef65cdUL ,
-     0xb5c0fbcfec4d3b2fUL ,  0xe9b5dba58189dbbcUL ,
-     0x3956c25bf348b538UL ,  0x59f111f1b605d019UL ,
-     0x923f82a4af194f9bUL ,  0xab1c5ed5da6d8118UL ,
-     0xd807aa98a3030242UL ,  0x12835b0145706fbeUL ,
-     0x243185be4ee4b28cUL ,  0x550c7dc3d5ffb4e2UL ,
-     0x72be5d74f27b896fUL ,  0x80deb1fe3b1696b1UL ,
-     0x9bdc06a725c71235UL ,  0xc19bf174cf692694UL ,
-     0xe49b69c19ef14ad2UL ,  0xefbe4786384f25e3UL ,
-     0x0fc19dc68b8cd5b5UL ,  0x240ca1cc77ac9c65UL ,
-     0x2de92c6f592b0275UL ,  0x4a7484aa6ea6e483UL ,
-     0x5cb0a9dcbd41fbd4UL ,  0x76f988da831153b5UL ,
-     0x983e5152ee66dfabUL ,  0xa831c66d2db43210UL ,
-     0xb00327c898fb213fUL ,  0xbf597fc7beef0ee4UL ,
-     0xc6e00bf33da88fc2UL ,  0xd5a79147930aa725UL ,
-     0x06ca6351e003826fUL ,  0x142929670a0e6e70UL ,
-     0x27b70a8546d22ffcUL ,  0x2e1b21385c26c926UL ,
-     0x4d2c6dfc5ac42aedUL ,  0x53380d139d95b3dfUL ,
-     0x650a73548baf63deUL ,  0x766a0abb3c77b2a8UL ,
-     0x81c2c92e47edaee6UL ,  0x92722c851482353bUL ,
-     0xa2bfe8a14cf10364UL ,  0xa81a664bbc423001UL ,
-     0xc24b8b70d0f89791UL ,  0xc76c51a30654be30UL ,
-     0xd192e819d6ef5218UL ,  0xd69906245565a910UL ,
-     0xf40e35855771202aUL ,  0x106aa07032bbd1b8UL ,
-     0x19a4c116b8d2d0c8UL ,  0x1e376c085141ab53UL ,
-     0x2748774cdf8eeb99UL ,  0x34b0bcb5e19b48a8UL ,
-     0x391c0cb3c5c95a63UL ,  0x4ed8aa4ae3418acbUL ,
-     0x5b9cca4f7763e373UL ,  0x682e6ff3d6b2b8a3UL ,
-     0x748f82ee5defb2fcUL ,  0x78a5636f43172f60UL ,
-     0x84c87814a1f0ab72UL ,  0x8cc702081a6439ecUL ,
-     0x90befffa23631e28UL ,  0xa4506cebde82bde9UL ,
-     0xbef9a3f7b2c67915UL ,  0xc67178f2e372532bUL ,
-     0xca273eceea26619cUL ,  0xd186b8c721c0c207UL ,
-     0xeada7dd6cde0eb1eUL ,  0xf57d4f7fee6ed178UL ,
-     0x06f067aa72176fbaUL ,  0x0a637dc5a2c898a6UL ,
-     0x113f9804bef90daeUL ,  0x1b710b35131c471bUL ,
-     0x28db77f523047d84UL ,  0x32caab7b40c72493UL ,
-     0x3c9ebe0a15c9bebcUL ,  0x431d67c49c100d4cUL ,
-     0x4cc5d4becb3e42b6UL ,  0x597f299cfc657e2aUL ,
-     0x5fcb6fab3ad6faecUL ,  0x6c44198c4a475817UL
-#else
-    ULLC(428a2f98,d728ae22), ULLC(71374491,23ef65cd),
-    ULLC(b5c0fbcf,ec4d3b2f), ULLC(e9b5dba5,8189dbbc),
-    ULLC(3956c25b,f348b538), ULLC(59f111f1,b605d019),
-    ULLC(923f82a4,af194f9b), ULLC(ab1c5ed5,da6d8118),
-    ULLC(d807aa98,a3030242), ULLC(12835b01,45706fbe),
-    ULLC(243185be,4ee4b28c), ULLC(550c7dc3,d5ffb4e2),
-    ULLC(72be5d74,f27b896f), ULLC(80deb1fe,3b1696b1),
-    ULLC(9bdc06a7,25c71235), ULLC(c19bf174,cf692694),
-    ULLC(e49b69c1,9ef14ad2), ULLC(efbe4786,384f25e3),
-    ULLC(0fc19dc6,8b8cd5b5), ULLC(240ca1cc,77ac9c65),
-    ULLC(2de92c6f,592b0275), ULLC(4a7484aa,6ea6e483),
-    ULLC(5cb0a9dc,bd41fbd4), ULLC(76f988da,831153b5),
-    ULLC(983e5152,ee66dfab), ULLC(a831c66d,2db43210),
-    ULLC(b00327c8,98fb213f), ULLC(bf597fc7,beef0ee4),
-    ULLC(c6e00bf3,3da88fc2), ULLC(d5a79147,930aa725),
-    ULLC(06ca6351,e003826f), ULLC(14292967,0a0e6e70),
-    ULLC(27b70a85,46d22ffc), ULLC(2e1b2138,5c26c926),
-    ULLC(4d2c6dfc,5ac42aed), ULLC(53380d13,9d95b3df),
-    ULLC(650a7354,8baf63de), ULLC(766a0abb,3c77b2a8),
-    ULLC(81c2c92e,47edaee6), ULLC(92722c85,1482353b),
-    ULLC(a2bfe8a1,4cf10364), ULLC(a81a664b,bc423001),
-    ULLC(c24b8b70,d0f89791), ULLC(c76c51a3,0654be30),
-    ULLC(d192e819,d6ef5218), ULLC(d6990624,5565a910),
-    ULLC(f40e3585,5771202a), ULLC(106aa070,32bbd1b8),
-    ULLC(19a4c116,b8d2d0c8), ULLC(1e376c08,5141ab53),
-    ULLC(2748774c,df8eeb99), ULLC(34b0bcb5,e19b48a8),
-    ULLC(391c0cb3,c5c95a63), ULLC(4ed8aa4a,e3418acb),
-    ULLC(5b9cca4f,7763e373), ULLC(682e6ff3,d6b2b8a3),
-    ULLC(748f82ee,5defb2fc), ULLC(78a5636f,43172f60),
-    ULLC(84c87814,a1f0ab72), ULLC(8cc70208,1a6439ec),
-    ULLC(90befffa,23631e28), ULLC(a4506ceb,de82bde9),
-    ULLC(bef9a3f7,b2c67915), ULLC(c67178f2,e372532b),
-    ULLC(ca273ece,ea26619c), ULLC(d186b8c7,21c0c207),
-    ULLC(eada7dd6,cde0eb1e), ULLC(f57d4f7f,ee6ed178),
-    ULLC(06f067aa,72176fba), ULLC(0a637dc5,a2c898a6),
-    ULLC(113f9804,bef90dae), ULLC(1b710b35,131c471b),
-    ULLC(28db77f5,23047d84), ULLC(32caab7b,40c72493),
-    ULLC(3c9ebe0a,15c9bebc), ULLC(431d67c4,9c100d4c),
-    ULLC(4cc5d4be,cb3e42b6), ULLC(597f299c,fc657e2a),
-    ULLC(5fcb6fab,3ad6faec), ULLC(6c44198c,4a475817)
-#endif
-};
-
-struct SHA512ContextStr {
-    union {
-	PRUint64 w[80];	    /* message schedule, input buffer, plus 64 words */
-	PRUint32 l[160];
-	PRUint8  b[640];
-    } u;
-    PRUint64 h[8];	    /* 8 state variables */
-    PRUint64 sizeLo;	    /* 64-bit count of hashed bytes. */
-};
-
-/* =========== SHA512 implementation ===================================== */
-
-/* SHA-512 initial hash values */
-static const PRUint64 H512[8] = {
-#if PR_BYTES_PER_LONG == 8
-     0x6a09e667f3bcc908UL ,  0xbb67ae8584caa73bUL ,
-     0x3c6ef372fe94f82bUL ,  0xa54ff53a5f1d36f1UL ,
-     0x510e527fade682d1UL ,  0x9b05688c2b3e6c1fUL ,
-     0x1f83d9abfb41bd6bUL ,  0x5be0cd19137e2179UL
-#else
-    ULLC(6a09e667,f3bcc908), ULLC(bb67ae85,84caa73b),
-    ULLC(3c6ef372,fe94f82b), ULLC(a54ff53a,5f1d36f1),
-    ULLC(510e527f,ade682d1), ULLC(9b05688c,2b3e6c1f),
-    ULLC(1f83d9ab,fb41bd6b), ULLC(5be0cd19,137e2179)
-#endif
-};
-
-
-SHA512Context *
-SHA512_NewContext(void)
-{
-    SHA512Context *ctx = PORT_New(SHA512Context);
-    return ctx;
-}
-
-void
-SHA512_DestroyContext(SHA512Context *ctx, PRBool freeit)
-{
-    if (freeit) {
-        PORT_ZFree(ctx, sizeof *ctx);
-    }
-}
-
-void
-SHA512_Begin(SHA512Context *ctx)
-{
-    memset(ctx, 0, sizeof *ctx);
-    memcpy(H, H512, sizeof H512);
-}
-
-#if defined(SHA512_TRACE)
-#if defined(HAVE_LONG_LONG)
-#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %016lx, %s = %016lx\n", \
-			       n, #e, d, #a, h);
-#else
-#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %08x%08x, %s = %08x%08x\n", \
-			       n, #e, d.hi, d.lo, #a, h.hi, h.lo);
-#endif
-#else
-#define DUMP(n,a,d,e,h)
-#endif
-
-#if defined(HAVE_LONG_LONG)
-
-#define ADDTO(x,y) y += x
-
-#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16])
-
-#define ROUND(n,a,b,c,d,e,f,g,h) \
-    h += S1(e) + Ch(e,f,g) + K512[n] + W[n]; \
-    d += h; \
-    h += S0(a) + Maj(a,b,c); \
-    DUMP(n,a,d,e,h)
-
-#else /* use only 32-bit variables, and don't unroll loops */
-
-#undef  NOUNROLL512
-#define NOUNROLL512 1
-
-#define ADDTO(x,y) y.lo += x.lo; y.hi += x.hi + (x.lo > y.lo)
-
-#define ROTR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n))
-#define ROTR64A(x,n,lo,hi) (x.lo << (64-n) | x.hi >> (n-32))
-#define  SHR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n))
-
-/* Capitol Sigma and lower case sigma functions */
-#define s0lo(x) (ROTR64a(x,1,lo,hi) ^ ROTR64a(x,8,lo,hi) ^ SHR64a(x,7,lo,hi))
-#define s0hi(x) (ROTR64a(x,1,hi,lo) ^ ROTR64a(x,8,hi,lo) ^ (x.hi >> 7))
-
-#define s1lo(x) (ROTR64a(x,19,lo,hi) ^ ROTR64A(x,61,lo,hi) ^ SHR64a(x,6,lo,hi))
-#define s1hi(x) (ROTR64a(x,19,hi,lo) ^ ROTR64A(x,61,hi,lo) ^ (x.hi >> 6))
-
-#define S0lo(x)(ROTR64a(x,28,lo,hi) ^ ROTR64A(x,34,lo,hi) ^ ROTR64A(x,39,lo,hi))
-#define S0hi(x)(ROTR64a(x,28,hi,lo) ^ ROTR64A(x,34,hi,lo) ^ ROTR64A(x,39,hi,lo))
-
-#define S1lo(x)(ROTR64a(x,14,lo,hi) ^ ROTR64a(x,18,lo,hi) ^ ROTR64A(x,41,lo,hi))
-#define S1hi(x)(ROTR64a(x,14,hi,lo) ^ ROTR64a(x,18,hi,lo) ^ ROTR64A(x,41,hi,lo))
-
-/* 32-bit versions of Ch and Maj */
-#define Chxx(x,y,z,lo) ((x.lo & y.lo) ^ (~x.lo & z.lo))
-#define Majx(x,y,z,lo) ((x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo))
-
-#define INITW(t) \
-    do { \
-	PRUint32 lo, tm; \
-	PRUint32 cy = 0; \
-	lo = s1lo(W[t-2]); \
-	lo += (tm = W[t-7].lo);     if (lo < tm) cy++; \
-	lo += (tm = s0lo(W[t-15])); if (lo < tm) cy++; \
-	lo += (tm = W[t-16].lo);    if (lo < tm) cy++; \
-	W[t].lo = lo; \
-	W[t].hi = cy + s1hi(W[t-2]) + W[t-7].hi + s0hi(W[t-15]) + W[t-16].hi; \
-    } while (0)
-
-#define ROUND(n,a,b,c,d,e,f,g,h) \
-    { \
-	PRUint32 lo, tm, cy; \
-	lo  = S1lo(e); \
-	lo += (tm = Chxx(e,f,g,lo));    cy = (lo < tm); \
-	lo += (tm = K512[n].lo);	if (lo < tm) cy++; \
-	lo += (tm =    W[n].lo);	if (lo < tm) cy++; \
-	h.lo += lo;			if (h.lo < lo) cy++; \
-	h.hi += cy + S1hi(e) + Chxx(e,f,g,hi) + K512[n].hi + W[n].hi; \
-	d.lo += h.lo; \
-	d.hi += h.hi + (d.lo < h.lo); \
-	lo  = S0lo(a);  \
-	lo += (tm = Majx(a,b,c,lo));	cy = (lo < tm); \
-	h.lo += lo;			if (h.lo < lo) cy++; \
-	h.hi += cy + S0hi(a) + Majx(a,b,c,hi); \
-	DUMP(n,a,d,e,h) \
-    }
-#endif
-
-static void
-SHA512_Compress(SHA512Context *ctx)
-{
-#if defined(IS_LITTLE_ENDIAN)
-  {
-#if defined(HAVE_LONG_LONG)
-    PRUint64 t1;
-#else
-    PRUint32 t1;
-#endif
-    BYTESWAP8(W[0]);
-    BYTESWAP8(W[1]);
-    BYTESWAP8(W[2]);
-    BYTESWAP8(W[3]);
-    BYTESWAP8(W[4]);
-    BYTESWAP8(W[5]);
-    BYTESWAP8(W[6]);
-    BYTESWAP8(W[7]);
-    BYTESWAP8(W[8]);
-    BYTESWAP8(W[9]);
-    BYTESWAP8(W[10]);
-    BYTESWAP8(W[11]);
-    BYTESWAP8(W[12]);
-    BYTESWAP8(W[13]);
-    BYTESWAP8(W[14]);
-    BYTESWAP8(W[15]);
-  }
-#endif
-
-  {
-    PRUint64 t1, t2;
-#ifdef NOUNROLL512
-    {
-	/* prepare the "message schedule"   */
-	int t;
-	for (t = 16; t < 80; ++t) {
-	    INITW(t);
-	}
-    }
-#else
-    INITW(16);
-    INITW(17);
-    INITW(18);
-    INITW(19);
-
-    INITW(20);
-    INITW(21);
-    INITW(22);
-    INITW(23);
-    INITW(24);
-    INITW(25);
-    INITW(26);
-    INITW(27);
-    INITW(28);
-    INITW(29);
-
-    INITW(30);
-    INITW(31);
-    INITW(32);
-    INITW(33);
-    INITW(34);
-    INITW(35);
-    INITW(36);
-    INITW(37);
-    INITW(38);
-    INITW(39);
-
-    INITW(40);
-    INITW(41);
-    INITW(42);
-    INITW(43);
-    INITW(44);
-    INITW(45);
-    INITW(46);
-    INITW(47);
-    INITW(48);
-    INITW(49);
-
-    INITW(50);
-    INITW(51);
-    INITW(52);
-    INITW(53);
-    INITW(54);
-    INITW(55);
-    INITW(56);
-    INITW(57);
-    INITW(58);
-    INITW(59);
-
-    INITW(60);
-    INITW(61);
-    INITW(62);
-    INITW(63);
-    INITW(64);
-    INITW(65);
-    INITW(66);
-    INITW(67);
-    INITW(68);
-    INITW(69);
-
-    INITW(70);
-    INITW(71);
-    INITW(72);
-    INITW(73);
-    INITW(74);
-    INITW(75);
-    INITW(76);
-    INITW(77);
-    INITW(78);
-    INITW(79);
-#endif
-  }
-#ifdef SHA512_TRACE
-  {
-    int i;
-    for (i = 0; i < 80; ++i) {
-#ifdef HAVE_LONG_LONG
-	printf("W[%2d] = %016lx\n", i, W[i]);
-#else
-	printf("W[%2d] = %08x%08x\n", i, W[i].hi, W[i].lo);
-#endif
-    }
-  }
-#endif
-  {
-    PRUint64 a, b, c, d, e, f, g, h;
-
-    a = H[0];
-    b = H[1];
-    c = H[2];
-    d = H[3];
-    e = H[4];
-    f = H[5];
-    g = H[6];
-    h = H[7];
-
-#ifdef NOUNROLL512
-    {
-	int t;
-	for (t = 0; t < 80; t+= 8) {
-	    ROUND(t+0,a,b,c,d,e,f,g,h)
-	    ROUND(t+1,h,a,b,c,d,e,f,g)
-	    ROUND(t+2,g,h,a,b,c,d,e,f)
-	    ROUND(t+3,f,g,h,a,b,c,d,e)
-	    ROUND(t+4,e,f,g,h,a,b,c,d)
-	    ROUND(t+5,d,e,f,g,h,a,b,c)
-	    ROUND(t+6,c,d,e,f,g,h,a,b)
-	    ROUND(t+7,b,c,d,e,f,g,h,a)
-	}
-    }
-#else
-    ROUND( 0,a,b,c,d,e,f,g,h)
-    ROUND( 1,h,a,b,c,d,e,f,g)
-    ROUND( 2,g,h,a,b,c,d,e,f)
-    ROUND( 3,f,g,h,a,b,c,d,e)
-    ROUND( 4,e,f,g,h,a,b,c,d)
-    ROUND( 5,d,e,f,g,h,a,b,c)
-    ROUND( 6,c,d,e,f,g,h,a,b)
-    ROUND( 7,b,c,d,e,f,g,h,a)
-
-    ROUND( 8,a,b,c,d,e,f,g,h)
-    ROUND( 9,h,a,b,c,d,e,f,g)
-    ROUND(10,g,h,a,b,c,d,e,f)
-    ROUND(11,f,g,h,a,b,c,d,e)
-    ROUND(12,e,f,g,h,a,b,c,d)
-    ROUND(13,d,e,f,g,h,a,b,c)
-    ROUND(14,c,d,e,f,g,h,a,b)
-    ROUND(15,b,c,d,e,f,g,h,a)
-
-    ROUND(16,a,b,c,d,e,f,g,h)
-    ROUND(17,h,a,b,c,d,e,f,g)
-    ROUND(18,g,h,a,b,c,d,e,f)
-    ROUND(19,f,g,h,a,b,c,d,e)
-    ROUND(20,e,f,g,h,a,b,c,d)
-    ROUND(21,d,e,f,g,h,a,b,c)
-    ROUND(22,c,d,e,f,g,h,a,b)
-    ROUND(23,b,c,d,e,f,g,h,a)
-
-    ROUND(24,a,b,c,d,e,f,g,h)
-    ROUND(25,h,a,b,c,d,e,f,g)
-    ROUND(26,g,h,a,b,c,d,e,f)
-    ROUND(27,f,g,h,a,b,c,d,e)
-    ROUND(28,e,f,g,h,a,b,c,d)
-    ROUND(29,d,e,f,g,h,a,b,c)
-    ROUND(30,c,d,e,f,g,h,a,b)
-    ROUND(31,b,c,d,e,f,g,h,a)
-
-    ROUND(32,a,b,c,d,e,f,g,h)
-    ROUND(33,h,a,b,c,d,e,f,g)
-    ROUND(34,g,h,a,b,c,d,e,f)
-    ROUND(35,f,g,h,a,b,c,d,e)
-    ROUND(36,e,f,g,h,a,b,c,d)
-    ROUND(37,d,e,f,g,h,a,b,c)
-    ROUND(38,c,d,e,f,g,h,a,b)
-    ROUND(39,b,c,d,e,f,g,h,a)
-
-    ROUND(40,a,b,c,d,e,f,g,h)
-    ROUND(41,h,a,b,c,d,e,f,g)
-    ROUND(42,g,h,a,b,c,d,e,f)
-    ROUND(43,f,g,h,a,b,c,d,e)
-    ROUND(44,e,f,g,h,a,b,c,d)
-    ROUND(45,d,e,f,g,h,a,b,c)
-    ROUND(46,c,d,e,f,g,h,a,b)
-    ROUND(47,b,c,d,e,f,g,h,a)
-
-    ROUND(48,a,b,c,d,e,f,g,h)
-    ROUND(49,h,a,b,c,d,e,f,g)
-    ROUND(50,g,h,a,b,c,d,e,f)
-    ROUND(51,f,g,h,a,b,c,d,e)
-    ROUND(52,e,f,g,h,a,b,c,d)
-    ROUND(53,d,e,f,g,h,a,b,c)
-    ROUND(54,c,d,e,f,g,h,a,b)
-    ROUND(55,b,c,d,e,f,g,h,a)
-
-    ROUND(56,a,b,c,d,e,f,g,h)
-    ROUND(57,h,a,b,c,d,e,f,g)
-    ROUND(58,g,h,a,b,c,d,e,f)
-    ROUND(59,f,g,h,a,b,c,d,e)
-    ROUND(60,e,f,g,h,a,b,c,d)
-    ROUND(61,d,e,f,g,h,a,b,c)
-    ROUND(62,c,d,e,f,g,h,a,b)
-    ROUND(63,b,c,d,e,f,g,h,a)
-
-    ROUND(64,a,b,c,d,e,f,g,h)
-    ROUND(65,h,a,b,c,d,e,f,g)
-    ROUND(66,g,h,a,b,c,d,e,f)
-    ROUND(67,f,g,h,a,b,c,d,e)
-    ROUND(68,e,f,g,h,a,b,c,d)
-    ROUND(69,d,e,f,g,h,a,b,c)
-    ROUND(70,c,d,e,f,g,h,a,b)
-    ROUND(71,b,c,d,e,f,g,h,a)
-
-    ROUND(72,a,b,c,d,e,f,g,h)
-    ROUND(73,h,a,b,c,d,e,f,g)
-    ROUND(74,g,h,a,b,c,d,e,f)
-    ROUND(75,f,g,h,a,b,c,d,e)
-    ROUND(76,e,f,g,h,a,b,c,d)
-    ROUND(77,d,e,f,g,h,a,b,c)
-    ROUND(78,c,d,e,f,g,h,a,b)
-    ROUND(79,b,c,d,e,f,g,h,a)
-#endif
-
-    ADDTO(a,H[0]);
-    ADDTO(b,H[1]);
-    ADDTO(c,H[2]);
-    ADDTO(d,H[3]);
-    ADDTO(e,H[4]);
-    ADDTO(f,H[5]);
-    ADDTO(g,H[6]);
-    ADDTO(h,H[7]);
-  }
-}
-
-void
-SHA512_Update(SHA512Context *ctx, const unsigned char *input,
-              unsigned int inputLen)
-{
-    unsigned int inBuf;
-    if (!inputLen)
-    	return;
-
-#if defined(HAVE_LONG_LONG)
-    inBuf = (unsigned int)ctx->sizeLo & 0x7f;
-    /* Add inputLen into the count of bytes processed, before processing */
-    ctx->sizeLo += inputLen;
-#else
-    inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f;
-    ctx->sizeLo.lo += inputLen;
-    if (ctx->sizeLo.lo < inputLen) ctx->sizeLo.hi++;
-#endif
-
-    /* if data already in buffer, attemp to fill rest of buffer */
-    if (inBuf) {
-    	unsigned int todo = SHA512_BLOCK_LENGTH - inBuf;
-	if (inputLen < todo)
-	    todo = inputLen;
-	memcpy(B + inBuf, input, todo);
-	input    += todo;
-	inputLen -= todo;
-	if (inBuf + todo == SHA512_BLOCK_LENGTH)
-	    SHA512_Compress(ctx);
-    }
-
-    /* if enough data to fill one or more whole buffers, process them. */
-    while (inputLen >= SHA512_BLOCK_LENGTH) {
-    	memcpy(B, input, SHA512_BLOCK_LENGTH);
-	input    += SHA512_BLOCK_LENGTH;
-	inputLen -= SHA512_BLOCK_LENGTH;
-	SHA512_Compress(ctx);
-    }
-    /* if data left over, fill it into buffer */
-    if (inputLen)
-    	memcpy(B, input, inputLen);
-}
-
-void
-SHA512_End(SHA512Context *ctx, unsigned char *digest,
-           unsigned int *digestLen, unsigned int maxDigestLen)
-{
-#if defined(HAVE_LONG_LONG)
-    unsigned int inBuf  = (unsigned int)ctx->sizeLo & 0x7f;
-    unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
-    PRUint64 lo, t1;
-    lo = (ctx->sizeLo << 3);
-#else
-    unsigned int inBuf  = (unsigned int)ctx->sizeLo.lo & 0x7f;
-    unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
-    PRUint64 lo = ctx->sizeLo;
-    PRUint32 t1;
-    lo.lo <<= 3;
-#endif
-
-    SHA512_Update(ctx, pad, padLen);
-
-#if defined(HAVE_LONG_LONG)
-    W[14] = 0;
-#else
-    W[14].lo = 0;
-    W[14].hi = 0;
-#endif
-
-    W[15] = lo;
-#if defined(IS_LITTLE_ENDIAN)
-    BYTESWAP8(W[15]);
-#endif
-    SHA512_Compress(ctx);
-
-    /* now output the answer */
-#if defined(IS_LITTLE_ENDIAN)
-    BYTESWAP8(H[0]);
-    BYTESWAP8(H[1]);
-    BYTESWAP8(H[2]);
-    BYTESWAP8(H[3]);
-    BYTESWAP8(H[4]);
-    BYTESWAP8(H[5]);
-    BYTESWAP8(H[6]);
-    BYTESWAP8(H[7]);
-#endif
-    padLen = PR_MIN(SHA512_LENGTH, maxDigestLen);
-    memcpy(digest, H, padLen);
-    if (digestLen)
-	*digestLen = padLen;
-}
-
-SECStatus
-SHA512_HashBuf(unsigned char *dest, const unsigned char *src,
-               unsigned int src_length)
-{
-    SHA512Context ctx;
-    unsigned int outLen;
-
-    SHA512_Begin(&ctx);
-    SHA512_Update(&ctx, src, src_length);
-    SHA512_End(&ctx, dest, &outLen, SHA512_LENGTH);
-
-    return SECSuccess;
-}
-
-
-SECStatus
-SHA512_Hash(unsigned char *dest, const char *src)
-{
-    return SHA512_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
-}
-
-
-void SHA512_TraceState(SHA512Context *ctx) { }
-
-unsigned int
-SHA512_FlattenSize(SHA512Context *ctx)
-{
-    return sizeof *ctx;
-}
-
-SECStatus
-SHA512_Flatten(SHA512Context *ctx,unsigned char *space)
-{
-    PORT_Memcpy(space, ctx, sizeof *ctx);
-    return SECSuccess;
-}
-
-SHA512Context *
-SHA512_Resurrect(unsigned char *space, void *arg)
-{
-    SHA512Context *ctx = SHA512_NewContext();
-    if (ctx)
-	PORT_Memcpy(ctx, space, sizeof *ctx);
-    return ctx;
-}
-
-void SHA512_Clone(SHA512Context *dest, SHA512Context *src)
-{
-    memcpy(dest, src, sizeof *dest);
-}
-
-/* ======================================================================= */
-/* SHA384 uses a SHA512Context as the real context.
-** The only differences between SHA384 an SHA512 are:
-** a) the intialization values for the context, and
-** b) the number of bytes of data produced as output.
-*/
-
-/* SHA-384 initial hash values */
-static const PRUint64 H384[8] = {
-#if PR_BYTES_PER_LONG == 8
-     0xcbbb9d5dc1059ed8UL ,  0x629a292a367cd507UL ,
-     0x9159015a3070dd17UL ,  0x152fecd8f70e5939UL ,
-     0x67332667ffc00b31UL ,  0x8eb44a8768581511UL ,
-     0xdb0c2e0d64f98fa7UL ,  0x47b5481dbefa4fa4UL
-#else
-    ULLC(cbbb9d5d,c1059ed8), ULLC(629a292a,367cd507),
-    ULLC(9159015a,3070dd17), ULLC(152fecd8,f70e5939),
-    ULLC(67332667,ffc00b31), ULLC(8eb44a87,68581511),
-    ULLC(db0c2e0d,64f98fa7), ULLC(47b5481d,befa4fa4)
-#endif
-};
-
-SHA384Context *
-SHA384_NewContext(void)
-{
-    return SHA512_NewContext();
-}
-
-void
-SHA384_DestroyContext(SHA384Context *ctx, PRBool freeit)
-{
-    SHA512_DestroyContext(ctx, freeit);
-}
-
-void
-SHA384_Begin(SHA384Context *ctx)
-{
-    memset(ctx, 0, sizeof *ctx);
-    memcpy(H, H384, sizeof H384);
-}
-
-void
-SHA384_Update(SHA384Context *ctx, const unsigned char *input,
-		    unsigned int inputLen)
-{
-    SHA512_Update(ctx, input, inputLen);
-}
-
-void
-SHA384_End(SHA384Context *ctx, unsigned char *digest,
-		 unsigned int *digestLen, unsigned int maxDigestLen)
-{
-#define SHA_MIN(a,b) (a < b ? a : b)
-    unsigned int maxLen = SHA_MIN(maxDigestLen, SHA384_LENGTH);
-    SHA512_End(ctx, digest, digestLen, maxLen);
-}
-
-SECStatus
-SHA384_HashBuf(unsigned char *dest, const unsigned char *src,
-			  unsigned int src_length)
-{
-    SHA512Context ctx;
-    unsigned int outLen;
-
-    SHA384_Begin(&ctx);
-    SHA512_Update(&ctx, src, src_length);
-    SHA512_End(&ctx, dest, &outLen, SHA384_LENGTH);
-
-    return SECSuccess;
-}
-
-SECStatus
-SHA384_Hash(unsigned char *dest, const char *src)
-{
-    return SHA384_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
-}
-
-void SHA384_TraceState(SHA384Context *ctx) { }
-
-unsigned int
-SHA384_FlattenSize(SHA384Context *ctx)
-{
-    return sizeof(SHA384Context);
-}
-
-SECStatus
-SHA384_Flatten(SHA384Context *ctx,unsigned char *space)
-{
-    return SHA512_Flatten(ctx, space);
-}
-
-SHA384Context *
-SHA384_Resurrect(unsigned char *space, void *arg)
-{
-    return SHA512_Resurrect(space, arg);
-}
-
-void SHA384_Clone(SHA384Context *dest, SHA384Context *src)
-{
-    memcpy(dest, src, sizeof *dest);
-}
-#endif  /* Comment out unused code. */
-
-/* ======================================================================= */
-#ifdef SELFTEST
-#include <stdio.h>
-
-static const char abc[] = { "abc" };
-static const char abcdbc[] = {
-    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-};
-static const char abcdef[] = {
-    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-    "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
-};
-
-void
-dumpHash32(const unsigned char *buf, unsigned int bufLen)
-{
-    unsigned int i;
-    for (i = 0; i < bufLen; i += 4) {
-	printf(" %02x%02x%02x%02x", buf[i], buf[i+1], buf[i+2], buf[i+3]);
-    }
-    printf("\n");
-}
-
-void test256(void)
-{
-    unsigned char outBuf[SHA256_LENGTH];
-
-    printf("SHA256, input = %s\n", abc);
-    SHA256_Hash(outBuf, abc);
-    dumpHash32(outBuf, sizeof outBuf);
-
-    printf("SHA256, input = %s\n", abcdbc);
-    SHA256_Hash(outBuf, abcdbc);
-    dumpHash32(outBuf, sizeof outBuf);
-}
-
-void
-dumpHash64(const unsigned char *buf, unsigned int bufLen)
-{
-    unsigned int i;
-    for (i = 0; i < bufLen; i += 8) {
-    	if (i % 32 == 0)
-	    printf("\n");
-	printf(" %02x%02x%02x%02x%02x%02x%02x%02x",
-	       buf[i  ], buf[i+1], buf[i+2], buf[i+3],
-	       buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
-    }
-    printf("\n");
-}
-
-void test512(void)
-{
-    unsigned char outBuf[SHA512_LENGTH];
-
-    printf("SHA512, input = %s\n", abc);
-    SHA512_Hash(outBuf, abc);
-    dumpHash64(outBuf, sizeof outBuf);
-
-    printf("SHA512, input = %s\n", abcdef);
-    SHA512_Hash(outBuf, abcdef);
-    dumpHash64(outBuf, sizeof outBuf);
-}
-
-void time512(void)
-{
-    unsigned char outBuf[SHA512_LENGTH];
-
-    SHA512_Hash(outBuf, abc);
-    SHA512_Hash(outBuf, abcdef);
-}
-
-void test384(void)
-{
-    unsigned char outBuf[SHA384_LENGTH];
-
-    printf("SHA384, input = %s\n", abc);
-    SHA384_Hash(outBuf, abc);
-    dumpHash64(outBuf, sizeof outBuf);
-
-    printf("SHA384, input = %s\n", abcdef);
-    SHA384_Hash(outBuf, abcdef);
-    dumpHash64(outBuf, sizeof outBuf);
-}
-
-int main (int argc, char *argv[], char *envp[])
-{
-    int i = 1;
-    if (argc > 1) {
-    	i = atoi(argv[1]);
-    }
-    if (i < 2) {
-	test256();
-	test512();
-	test384();
-    } else {
-    	while (i-- > 0) {
-	    time512();
-	}
-	printf("done\n");
-    }
-    return 0;
-}
-
-#endif
diff --git a/src/crypto/wincrypt_shim.h b/src/crypto/wincrypt_shim.h
new file mode 100644
index 0000000..d131431
--- /dev/null
+++ b/src/crypto/wincrypt_shim.h
@@ -0,0 +1,27 @@
+// Copyright 2014 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_WINCRYPT_SHIM_H_
+#define CRYPTO_WINCRYPT_SHIM_H_
+
+// wincrypt.h defines macros which conflict with OpenSSL's types. This header
+// includes wincrypt and undefines the OpenSSL macros which conflict. Any
+// Chromium headers which include wincrypt should instead include this header.
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include "starboard/types.h"
+
+// Undefine the macros which conflict with OpenSSL and define replacements. See
+// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378145(v=vs.85).aspx
+#undef X509_CERT_PAIR
+#undef X509_EXTENSIONS
+#undef X509_NAME
+
+#define WINCRYPT_X509_CERT_PAIR ((LPCSTR) 53)
+#define WINCRYPT_X509_EXTENSIONS ((LPCSTR) 5)
+#define WINCRYPT_X509_NAME ((LPCSTR) 7)
+
+#endif  // CRYPTO_WINCRYPT_SHIM_H_