[crypto] Add scrypt key derivation to SymmetricKey

Add a method for key derivation using the scrypt algorithm to
crypto::SymmetricKey.

Rename the pre-existing method for key derivation (which uses PBKDF2) to
clearly disambiguate between the two.

TBRing because all the changes to files not under crypto/ are a trivial
library method name change.

[email protected],[email protected],[email protected],[email protected],[email protected]

Bug: 875931
Change-Id: Iaa0b2bb0fc3ae2481733072363718cffd8811b97
Reviewed-on: https://chromium-review.googlesource.com/1181881
Commit-Queue: David Davidović <[email protected]>
Reviewed-by: David Benjamin <[email protected]>
Reviewed-by: vitaliii <[email protected]>
Cr-Commit-Position: refs/heads/master@{#586247}
diff --git a/chrome/browser/chromeos/settings/token_encryptor.cc b/chrome/browser/chromeos/settings/token_encryptor.cc
index 1965ae82..b52c89b 100644
--- a/chrome/browser/chromeos/settings/token_encryptor.cc
+++ b/chrome/browser/chromeos/settings/token_encryptor.cc
@@ -70,7 +70,7 @@
 std::unique_ptr<crypto::SymmetricKey> CryptohomeTokenEncryptor::PassphraseToKey(
     const std::string& passphrase,
     const std::string& salt) {
-  return crypto::SymmetricKey::DeriveKeyFromPassword(
+  return crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
       crypto::SymmetricKey::AES, passphrase, salt, 1000, 256);
 }
 
diff --git a/chrome/browser/signin/local_auth.cc b/chrome/browser/signin/local_auth.cc
index 5ce69c4..09af654 100644
--- a/chrome/browser/signin/local_auth.cc
+++ b/chrome/browser/signin/local_auth.cc
@@ -105,7 +105,7 @@
 
   // Library call to create secure password hash as SymmetricKey (uses PBKDF2).
   std::unique_ptr<crypto::SymmetricKey> password_key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, password, salt, encoding.iteration_count,
           encoding.hash_bits));
   std::string password_hash = password_key->key();
diff --git a/chromeos/login/auth/authpolicy_login_helper.cc b/chromeos/login/auth/authpolicy_login_helper.cc
index cc56973..a396b86 100644
--- a/chromeos/login/auth/authpolicy_login_helper.cc
+++ b/chromeos/login/auth/authpolicy_login_helper.cc
@@ -88,7 +88,7 @@
   const size_t kHmacKeySize = 32;
   const size_t kKeySize = kAesKeySize + kAesIvSize + kHmacKeySize;
   std::unique_ptr<crypto::SymmetricKey> key =
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::HMAC_SHA1, password, salt, 10000, kKeySize * 8);
   if (!key) {
     LOG(ERROR) << error_msg;
diff --git a/chromeos/login/auth/key.cc b/chromeos/login/auth/key.cc
index b1b9061..cd26dba1 100644
--- a/chromeos/login/auth/key.cc
+++ b/chromeos/login/auth/key.cc
@@ -85,7 +85,7 @@
     }
     case KEY_TYPE_SALTED_PBKDF2_AES256_1234: {
       std::unique_ptr<crypto::SymmetricKey> key(
-          crypto::SymmetricKey::DeriveKeyFromPassword(
+          crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
               crypto::SymmetricKey::AES, secret_, salt, kNumIterations,
               kKeySizeInBits));
       base::Base64Encode(key->key(), &secret_);
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index df75587..1109e30 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -721,9 +721,9 @@
   }
 
   std::unique_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
-                                                  passphrase, salt, iterations,
-                                                  kKeySizeInBits));
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, passphrase, salt, iterations,
+          kKeySizeInBits));
 
   if (!base::Base64Decode(initial_vector, &initial_vector)) {
     NET_LOG(ERROR) << kUnableToDecode;
diff --git a/components/os_crypt/os_crypt_linux.cc b/components/os_crypt/os_crypt_linux.cc
index 6510c68..6b9c384 100644
--- a/components/os_crypt/os_crypt_linux.cc
+++ b/components/os_crypt/os_crypt_linux.cc
@@ -121,7 +121,7 @@
 
   // Create an encryption key from our password and salt.
   std::unique_ptr<crypto::SymmetricKey> encryption_key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, *password, salt, kEncryptionIterations,
           kDerivedKeySizeInBits));
   DCHECK(encryption_key);
diff --git a/components/os_crypt/os_crypt_mac.mm b/components/os_crypt/os_crypt_mac.mm
index 7913d5a3..c0b046c 100644
--- a/components/os_crypt/os_crypt_mac.mm
+++ b/components/os_crypt/os_crypt_mac.mm
@@ -87,10 +87,11 @@
 
   // Create an encryption key from our password and salt. The key is
   // intentionally leaked.
-  cached_encryption_key = crypto::SymmetricKey::DeriveKeyFromPassword(
-                              crypto::SymmetricKey::AES, password, salt,
-                              kEncryptionIterations, kDerivedKeySizeInBits)
-                              .release();
+  cached_encryption_key =
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, password, salt, kEncryptionIterations,
+          kDerivedKeySizeInBits)
+          .release();
   ANNOTATE_LEAKING_OBJECT_PTR(cached_encryption_key);
   DCHECK(cached_encryption_key);
   return cached_encryption_key;
diff --git a/components/os_crypt/os_crypt_posix.cc b/components/os_crypt/os_crypt_posix.cc
index 24a411e..9f190f7c 100644
--- a/components/os_crypt/os_crypt_posix.cc
+++ b/components/os_crypt/os_crypt_posix.cc
@@ -46,11 +46,9 @@
 
   // Create an encryption key from our password and salt.
   std::unique_ptr<crypto::SymmetricKey> encryption_key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
-                                                  password,
-                                                  salt,
-                                                  kEncryptionIterations,
-                                                  kDerivedKeySizeInBits));
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES, password, salt, kEncryptionIterations,
+          kDerivedKeySizeInBits));
   DCHECK(encryption_key.get());
 
   return encryption_key.release();
diff --git a/components/sync/base/nigori.cc b/components/sync/base/nigori.cc
index edbad0b..7566cd2e 100644
--- a/components/sync/base/nigori.cc
+++ b/components/sync/base/nigori.cc
@@ -69,25 +69,26 @@
   salt_password << username << hostname;
 
   // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8)
-  std::unique_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword(
-      SymmetricKey::HMAC_SHA1, salt_password.str(), kSaltSalt, kSaltIterations,
-      kSaltKeySizeInBits));
+  std::unique_ptr<SymmetricKey> user_salt(
+      SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          SymmetricKey::HMAC_SHA1, salt_password.str(), kSaltSalt,
+          kSaltIterations, kSaltKeySizeInBits));
   DCHECK(user_salt);
 
   // Kuser = PBKDF2(P, Suser, Nuser, 16)
-  user_key_ = SymmetricKey::DeriveKeyFromPassword(
+  user_key_ = SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
       SymmetricKey::AES, password, user_salt->key(), kUserIterations,
       kDerivedKeySizeInBits);
   DCHECK(user_key_);
 
   // Kenc = PBKDF2(P, Suser, Nenc, 16)
-  encryption_key_ = SymmetricKey::DeriveKeyFromPassword(
+  encryption_key_ = SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
       SymmetricKey::AES, password, user_salt->key(), kEncryptionIterations,
       kDerivedKeySizeInBits);
   DCHECK(encryption_key_);
 
   // Kmac = PBKDF2(P, Suser, Nmac, 16)
-  mac_key_ = SymmetricKey::DeriveKeyFromPassword(
+  mac_key_ = SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
       SymmetricKey::HMAC_SHA1, password, user_salt->key(), kSigningIterations,
       kDerivedKeySizeInBits);
   DCHECK(mac_key_);
diff --git a/crypto/encryptor_unittest.cc b/crypto/encryptor_unittest.cc
index 2294bdb..76178dcb 100644
--- a/crypto/encryptor_unittest.cc
+++ b/crypto/encryptor_unittest.cc
@@ -16,7 +16,7 @@
 
 TEST(EncryptorTest, EncryptDecrypt) {
   std::unique_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256));
   EXPECT_TRUE(key.get());
 
@@ -40,27 +40,27 @@
 
 TEST(EncryptorTest, DecryptWrongKey) {
   std::unique_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256));
   EXPECT_TRUE(key.get());
 
   // A wrong key that can be detected by implementations that validate every
   // byte in the padding.
   std::unique_ptr<crypto::SymmetricKey> wrong_key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      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.
   std::unique_ptr<crypto::SymmetricKey> wrong_key2(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      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.
   std::unique_ptr<crypto::SymmetricKey> wrong_key3(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES, "wrongwordx", "sweetest", 1000, 256));
   EXPECT_TRUE(wrong_key3.get());
 
diff --git a/crypto/symmetric_key.cc b/crypto/symmetric_key.cc
index 55ffb72f..b239d22c 100644
--- a/crypto/symmetric_key.cc
+++ b/crypto/symmetric_key.cc
@@ -18,6 +18,26 @@
 
 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.
 }
@@ -50,32 +70,22 @@
 }
 
 // static
-std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPassword(
+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) {
-  DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
-
-  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 (key_size_in_bits != 128 && key_size_in_bits != 256)
-      return nullptr;
-  }
+  if (!CheckDerivationParameters(algorithm, key_size_in_bits))
+    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 = PKCS5_PBKDF2_HMAC_SHA1(
       password.data(), password.length(),
       reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
@@ -85,6 +95,34 @@
 }
 
 // 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) {
diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h
index 9803cdc..d802241 100644
--- a/crypto/symmetric_key.h
+++ b/crypto/symmetric_key.h
@@ -41,17 +41,34 @@
   // 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 std::unique_ptr<SymmetricKey> DeriveKeyFromPassword(
+  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
-  // key(). The key must be of suitable size for use with |algorithm|.
-  // The caller owns the returned SymmetricKey.
+  // 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);
 
diff --git a/crypto/symmetric_key_unittest.cc b/crypto/symmetric_key_unittest.cc
index 02f12e5..6bef6ca 100644
--- a/crypto/symmetric_key_unittest.cc
+++ b/crypto/symmetric_key_unittest.cc
@@ -40,7 +40,7 @@
 
 TEST(SymmetricKeyTest, ImportDerivedKey) {
   std::unique_ptr<crypto::SymmetricKey> key1(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160));
   ASSERT_TRUE(key1);
 
@@ -57,17 +57,31 @@
   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());
   std::unique_ptr<crypto::SymmetricKey> key(
-      crypto::SymmetricKey::DeriveKeyFromPassword(
+      crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           test_data.algorithm, test_data.password, test_data.salt,
           test_data.rounds, test_data.key_size_in_bits));
   ASSERT_TRUE(key);
@@ -79,34 +93,41 @@
                                                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,
@@ -118,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",
-    "\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",
-  },
+    // 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/extensions/browser/api/lock_screen_data/data_item_unittest.cc b/extensions/browser/api/lock_screen_data/data_item_unittest.cc
index a12783f..47cb9d5 100644
--- a/extensions/browser/api/lock_screen_data/data_item_unittest.cc
+++ b/extensions/browser/api/lock_screen_data/data_item_unittest.cc
@@ -114,7 +114,7 @@
 
   std::string GenerateKey(const std::string& password) {
     std::unique_ptr<crypto::SymmetricKey> key =
-        crypto::SymmetricKey::DeriveKeyFromPassword(
+        crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
             crypto::SymmetricKey::AES, password, "salt", 1000, 256);
     if (!key) {
       ADD_FAILURE() << "Failed to create symmetric key";
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
index 8594ade..a42299b 100644
--- a/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
+++ b/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
@@ -138,7 +138,7 @@
 
   std::string GenerateKey(const std::string& password) {
     std::unique_ptr<crypto::SymmetricKey> key =
-        crypto::SymmetricKey::DeriveKeyFromPassword(
+        crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
             crypto::SymmetricKey::AES, password, "salt", 1000, 256);
     if (!key) {
       ADD_FAILURE() << "Failed to create symmetric key";
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index aed773f1..0efacd1 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -65,12 +65,12 @@
 
 CookieCryptor::CookieCryptor()
     : should_encrypt_(true),
-      key_(
-          crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
-                                                      "password",
-                                                      "saltiest",
-                                                      1000,
-                                                      256)) {
+      key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+          crypto::SymmetricKey::AES,
+          "password",
+          "saltiest",
+          1000,
+          256)) {
   std::string iv("the iv: 16 bytes");
   encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv);
 }