diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 482ab4a97c1e6..ed480bd6f995f 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -11777,6 +11777,21 @@ Some features may be unavailable.  Please check that the profile exists and you
       <message name="IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT" desc="Error for network configuration: Certificate import error.">
         Certificate import error
       </message>
+      <message name="IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_MALFORMED" desc="Displayed when importing an encrypted ONC file and the ONC file is malformed.">
+        Encrypted ONC file is malformed.
+      </message>
+      <message name="IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNSUPPORTED_ENCRYPTION" desc="Displayed when importing an encrypted ONC file and the ONC file uses an encryption protocol that is not supported.">
+        Encrypted ONC file uses an unsupported encryption scheme.
+      </message>
+      <message name="IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE" desc="Displayed when importing an encrypted ONC file and the encryption parameters are not able to be parsed.">
+        Unable to parse some parameters in the encrypted ONC file.
+      </message>
+      <message name="IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT" desc="Displayed when importing an encrypted ONC file and it is not able to be decrypted.">
+        Unable to decrypt the encrypted ONC file.
+      </message>
+      <message name="IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_TOO_MANY_ITERATIONS" desc="Displayed when importing an encrypted ONC file and the iteration count is too large.">
+        Passphrase iteration count is too large.
+      </message>
       <message name="IDS_NETWORK_PURCHASE_MORE_MESSAGE" desc="Message for purchase more link on notification when there is no cellular plan">
         Buy plan...
       </message>
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index a1e40526d68cd..2fbff69dca631 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -1773,7 +1773,7 @@ class NetworkLibraryImplBase : public NetworkLibrary  {
   // virtual SetIPConfig implemented in derived classes.
   virtual void SwitchToPreferredNetwork() OVERRIDE;
   virtual bool LoadOncNetworks(const std::string& onc_blob,
-                               const std::string& passcode,
+                               const std::string& passphrase,
                                NetworkUIData::ONCSource source,
                                std::string* error) OVERRIDE;
   virtual bool SetActiveNetwork(ConnectionType type,
@@ -2891,11 +2891,10 @@ void NetworkLibraryImplBase::SwitchToPreferredNetwork() {
 }
 
 bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob,
-                                             const std::string& passcode,
+                                             const std::string& passphrase,
                                              NetworkUIData::ONCSource source,
                                              std::string* error) {
-  // TODO(gspencer): Add support for decrypting onc files. crbug.com/19397
-  OncNetworkParser parser(onc_blob, source);
+  OncNetworkParser parser(onc_blob, passphrase, source);
 
   if (!parser.parse_error().empty()) {
     if (error)
diff --git a/chrome/browser/chromeos/cros/onc_network_parser.cc b/chrome/browser/chromeos/cros/onc_network_parser.cc
index 7b4c224d1cf93..6a0f577a732fb 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser.cc
+++ b/chrome/browser/chromeos/cros/onc_network_parser.cc
@@ -17,6 +17,10 @@
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/cros/onc_constants.h"
 #include "chrome/common/net/x509_certificate_model.h"
+#include "crypto/encryptor.h"
+#include "crypto/hmac.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/symmetric_key.h"
 #include "grit/generated_resources.h"
 #include "net/base/cert_database.h"
 #include "net/base/crypto_module.h"
@@ -199,6 +203,7 @@ std::string ConvertValueToString(const base::Value& value) {
 // -------------------- OncNetworkParser --------------------
 
 OncNetworkParser::OncNetworkParser(const std::string& onc_blob,
+                                   const std::string& passphrase,
                                    NetworkUIData::ONCSource onc_source)
     : NetworkParser(get_onc_mapper()),
       onc_source_(onc_source),
@@ -213,15 +218,25 @@ OncNetworkParser::OncNetworkParser(const std::string& onc_blob,
     LOG(WARNING) << "OncNetworkParser received bad ONC file: " << parse_error_;
   } else {
     root_dict_.reset(static_cast<DictionaryValue*>(root.release()));
+
+    // Check and see if this is an encrypted ONC file.  If so, decrypt it.
+    std::string ciphertext_test;
+    if (root_dict_->GetString("Ciphertext", &ciphertext_test))
+      root_dict_.reset(Decrypt(passphrase, root_dict_.get()));
+
+    // Decryption failed, errors will be in parse_error_;
+    if (!root_dict_.get())
+      return;
+
     // At least one of NetworkConfigurations or Certificates is required.
     bool has_network_configurations =
-      root_dict_->GetList("NetworkConfigurations", &network_configs_);
+        root_dict_->GetList("NetworkConfigurations", &network_configs_);
     bool has_certificates =
-      root_dict_->GetList("Certificates", &certificates_);
+        root_dict_->GetList("Certificates", &certificates_);
     VLOG(2) << "ONC file has " << GetNetworkConfigsSize() << " networks and "
             << GetCertificatesSize() << " certificates";
     LOG_IF(WARNING, (!has_network_configurations && !has_certificates))
-      << "ONC file has no NetworkConfigurations or Certificates.";
+        << "ONC file has no NetworkConfigurations or Certificates.";
   }
 }
 
@@ -239,6 +254,117 @@ const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() {
   return get_onc_mapper();
 }
 
+base::DictionaryValue* OncNetworkParser::Decrypt(
+    const std::string& passphrase,
+    base::DictionaryValue* root) {
+  const int kKeySizeInBits = 256;
+  const int kMaxIterationCount = 500000;
+  std::string onc_type;
+  std::string initial_vector;
+  std::string salt;
+  std::string cipher;
+  std::string stretch_method;
+  std::string hmac_method;
+  std::string hmac;
+  int iterations;
+  std::string ciphertext;
+
+  if (!root->GetString("Ciphertext", &ciphertext) ||
+      !root->GetString("Cipher", &cipher) ||
+      !root->GetString("HMAC", &hmac) ||
+      !root->GetString("HMACMethod", &hmac_method) ||
+      !root->GetString("IV", &initial_vector) ||
+      !root->GetInteger("Iterations", &iterations) ||
+      !root->GetString("Salt", &salt) ||
+      !root->GetString("Stretch", &stretch_method) ||
+      !root->GetString("Type", &onc_type) ||
+      onc_type != "EncryptedConfiguration") {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_MALFORMED);
+    return NULL;
+  }
+
+  if (hmac_method != "SHA1" ||
+      cipher != "AES256" ||
+      stretch_method != "PBKDF2") {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNSUPPORTED_ENCRYPTION);
+    return NULL;
+  }
+
+  // Simply a sanity check to make sure we can't lock up the machine
+  // for too long with a huge number.
+  if (iterations > kMaxIterationCount) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_TOO_MANY_ITERATIONS);
+    return NULL;
+  }
+
+  if (!base::Base64Decode(salt, &salt)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE);
+    return NULL;
+  }
+
+  scoped_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
+                                                  passphrase,
+                                                  salt,
+                                                  iterations,
+                                                  kKeySizeInBits));
+
+  if (!base::Base64Decode(initial_vector, &initial_vector)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE);
+    return NULL;
+  }
+  if (!base::Base64Decode(ciphertext, &ciphertext)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE);
+    return NULL;
+  }
+  if (!base::Base64Decode(hmac, &hmac)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE);
+    return NULL;
+  }
+
+  crypto::HMAC hmac_verifier(crypto::HMAC::SHA1);
+  if (!hmac_verifier.Init(key.get()) ||
+      !hmac_verifier.Verify(ciphertext, hmac)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT);
+    return NULL;
+  }
+
+  crypto::Encryptor decryptor;
+  if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector))  {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT);
+    return NULL;
+  }
+
+  std::string plaintext;
+  if (!decryptor.Decrypt(ciphertext, &plaintext)) {
+    parse_error_ = l10n_util::GetStringUTF8(
+        IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT);
+    return NULL;
+  }
+
+  // Now we've decrypted it, let's deserialize the decrypted data.
+  JSONStringValueSerializer deserializer(plaintext);
+  deserializer.set_allow_trailing_comma(true);
+  scoped_ptr<base::Value> new_root(deserializer.Deserialize(NULL,
+                                                            &parse_error_));
+  if (!new_root.get() || !new_root->IsType(base::Value::TYPE_DICTIONARY)) {
+    if (parse_error_.empty())
+      parse_error_ = l10n_util::GetStringUTF8(
+          IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED);
+    return NULL;
+  }
+  return static_cast<base::DictionaryValue*>(new_root.release());
+}
+
 int OncNetworkParser::GetNetworkConfigsSize() const {
   return network_configs_ ? network_configs_->GetSize() : 0;
 }
diff --git a/chrome/browser/chromeos/cros/onc_network_parser.h b/chrome/browser/chromeos/cros/onc_network_parser.h
index af55c27d4d77c..1e9cc3015d0d2 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser.h
+++ b/chrome/browser/chromeos/cros/onc_network_parser.h
@@ -53,6 +53,7 @@ class OncNetworkParser : public NetworkParser {
                                 Network*);
 
   OncNetworkParser(const std::string& onc_blob,
+                   const std::string& passphrase,
                    NetworkUIData::ONCSource onc_source);
   virtual ~OncNetworkParser();
   static const EnumMapper<PropertyIndex>* property_mapper();
@@ -147,6 +148,9 @@ class OncNetworkParser : public NetworkParser {
     const std::string& guid,
     base::DictionaryValue* certificate);
 
+  base::DictionaryValue* Decrypt(const std::string& passphrase,
+                                 base::DictionaryValue* root);
+
   // Error message from the JSON parser, if applicable.
   std::string parse_error_;
 
diff --git a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
index fb63bb4414edf..696bbc3dc5b13 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
+++ b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
@@ -469,7 +469,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkWifi1) {
       "    }"
       "  }]"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetNetworkConfigsSize());
   EXPECT_EQ(0, parser.GetCertificatesSize());
@@ -487,6 +487,46 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkWifi1) {
   CheckStringProperty(wifi, PROPERTY_INDEX_PASSPHRASE, "pass");
 }
 
+TEST_F(OncNetworkParserTest, TestLoadEncryptedOnc) {
+  std::string test_blob(
+      "{"
+      "  \"Cipher\": \"AES256\","
+      "  \"Ciphertext\": \"eQ9/r6v29/83M745aa0JllEj4lklt3Nfy4kPPvXgjBt1eTBy"
+      "xXB+FnsdvL6Uca5JBU5aROxfiol2+ZZOkxPmUNNIFZj70pkdqOGVe09ncf0aVBDsAa27"
+      "veGIG8rG/VQTTbAo7d8QaxdNNbZvwQVkdsAXawzPCu7zSh4NF/hDnDbYjbN/JEm1NzvW"
+      "gEjeOfqnnw3PnGUYCArIaRsKq9uD0a1NccU+16ZSzyDhX724JNrJjsuxohotk5YXsCK0"
+      "lP7ZXuXj+nSR0aRIETSQ+eqGhrew2octLXq8cXK05s6ZuVAc0mFKPkntSI/fzBACuPi4"
+      "ZaGd3YEYiKzNOgKJ+qEwgoE39xp0EXMZOZyjMOAtA6e1ZZDQGWG7vKdTLmLKNztHGrXv"
+      "lZkyEf1RDs10YgkwwLgUhm0yBJ+eqbxO/RiBXz7O2/UVOkkkVcmeI6yh3BdL6HIYsMMy"
+      "gnZa5WRkd/2/EudoqEnjcqUyGsL+YUqV6KRTC0PH+z7zSwvFs2KygrSM7SIAZM2yiQHT"
+      "QACkA/YCJDwACkkQOBFnRWTWiX0xmN55WMbgrs/wqJ4zGC9LgdAInOBlc3P+76+i7QLa"
+      "NjMovQ==\","
+      "  \"HMAC\": \"3ylRy5InlhVzFGakJ/9lvGSyVH0=\","
+      "  \"HMACMethod\": \"SHA1\","
+      "  \"IV\": \"hcm6OENfqG6C/TVO6p5a8g==\","
+      "  \"Iterations\": 20000,"
+      "  \"Salt\": \"/3O73QadCzA=\","
+      "  \"Stretch\": \"PBKDF2\","
+      "  \"Type\": \"EncryptedConfiguration\""
+      "}");
+  OncNetworkParser parser(test_blob,
+                          "test0000",
+                          NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  ASSERT_TRUE(parser.parse_error().empty());
+  EXPECT_EQ(1, parser.GetNetworkConfigsSize());
+  EXPECT_EQ(0, parser.GetCertificatesSize());
+  scoped_ptr<Network> network(parser.ParseNetwork(0));
+  ASSERT_TRUE(network.get());
+
+  EXPECT_EQ(network->type(), chromeos::TYPE_WIFI);
+  WifiNetwork* wifi = static_cast<WifiNetwork*>(network.get());
+  EXPECT_EQ(wifi->encryption(), chromeos::SECURITY_NONE);
+  EXPECT_EQ(wifi->name(), "WirelessNetwork");
+  EXPECT_EQ(wifi->auto_connect(), false);
+  EXPECT_EQ(wifi->passphrase(), "");
+}
+
+
 TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP1) {
   std::string test_blob(
       "{"
@@ -504,7 +544,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP1) {
       "    }"
       "  }]"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetNetworkConfigsSize());
   EXPECT_EQ(0, parser.GetCertificatesSize());
@@ -543,7 +583,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP2) {
       "    }"
       "  }]"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetNetworkConfigsSize());
   EXPECT_EQ(0, parser.GetCertificatesSize());
@@ -582,7 +622,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkUnknownFields) {
       "    },"
       "  }]"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
   scoped_ptr<Network> network(parser.ParseNetwork(0));
   ASSERT_TRUE(network.get());
 
@@ -599,7 +639,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkOpenVPN) {
       "  \"NetworkConfigurations\": [") +
       std::string(kNetworkConfigurationOpenVPN) + std::string(
       "  ]}"));
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetNetworkConfigsSize());
   EXPECT_EQ(0, parser.GetCertificatesSize());
@@ -678,7 +718,7 @@ TEST_F(OncNetworkParserTest, TestCreateNetworkL2TPIPsec) {
       "  ],"
       "  \"Certificates\": []"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetNetworkConfigsSize());
   EXPECT_EQ(0, parser.GetCertificatesSize());
@@ -709,7 +749,7 @@ TEST_F(OncNetworkParserTest, TestAddClientCertificate) {
       "    ],"
       "}");
   std::string test_guid("{f998f760-272b-6939-4c2beffe428697ac}");
-  OncNetworkParser parser(certificate_json,
+  OncNetworkParser parser(certificate_json, "",
                           NetworkUIData::ONC_SOURCE_USER_IMPORT);
   ASSERT_EQ(1, parser.GetCertificatesSize());
 
@@ -774,7 +814,7 @@ TEST_F(OncNetworkParserTest, TestReplaceClientCertificate) {
   std::string test_guid("{f998f760-272b-6939-4c2beffe428697ac}");
   {
     // First we import a certificate.
-    OncNetworkParser parser(certificate_json,
+    OncNetworkParser parser(certificate_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
 
@@ -793,7 +833,7 @@ TEST_F(OncNetworkParserTest, TestReplaceClientCertificate) {
   {
     // Now we import a new certificate with the same GUID as the
     // first.  It should replace the old one.
-    OncNetworkParser parser(certificate_alternate_json,
+    OncNetworkParser parser(certificate_alternate_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
     scoped_refptr<net::X509Certificate> cert = parser.ParseCertificate(0).get();
@@ -815,7 +855,7 @@ TEST_F(OncNetworkParserTest, TestAddServerCertificate) {
       "    ],"
       "}");
   std::string test_guid("{f998f760-272b-6939-4c2beffe428697aa}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
   ASSERT_EQ(1, parser.GetCertificatesSize());
 
   scoped_refptr<net::X509Certificate> cert = parser.ParseCertificate(0).get();
@@ -856,7 +896,7 @@ TEST_F(OncNetworkParserTest, TestReplaceServerCertificate) {
   std::string test_guid("{f998f760-272b-6939-4c2beffe428697aa}");
   {
     // First we import a certificate.
-    OncNetworkParser parser(certificate_json,
+    OncNetworkParser parser(certificate_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
 
@@ -875,7 +915,7 @@ TEST_F(OncNetworkParserTest, TestReplaceServerCertificate) {
   {
     // Now we import a new certificate with the same GUID as the
     // first.  It should replace the old one.
-    OncNetworkParser parser(certificate_alternate_json,
+    OncNetworkParser parser(certificate_alternate_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
     scoped_refptr<net::X509Certificate> cert = parser.ParseCertificate(0).get();
@@ -898,7 +938,7 @@ TEST_F(OncNetworkParserTest, TestAddAuthorityCertificate) {
       "    ],"
       "}");
   std::string test_guid("{f998f760-272b-6939-4c2beffe428697ab}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "", NetworkUIData::ONC_SOURCE_USER_IMPORT);
   ASSERT_EQ(1, parser.GetCertificatesSize());
 
   scoped_refptr<net::X509Certificate> cert = parser.ParseCertificate(0).get();
@@ -938,7 +978,7 @@ TEST_F(OncNetworkParserTest, TestReplaceAuthorityCertificate) {
 
   {
     // First we import an authority certificate.
-    OncNetworkParser parser(authority_json,
+    OncNetworkParser parser(authority_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
 
@@ -957,7 +997,7 @@ TEST_F(OncNetworkParserTest, TestReplaceAuthorityCertificate) {
   {
     // Now we import a new authority certificate with the same GUID as the
     // first.  It should replace the old one.
-    OncNetworkParser parser(authority_alternate_json,
+    OncNetworkParser parser(authority_alternate_json, "",
                             NetworkUIData::ONC_SOURCE_USER_IMPORT);
     ASSERT_EQ(1, parser.GetCertificatesSize());
     scoped_refptr<net::X509Certificate> cert = parser.ParseCertificate(0).get();
@@ -982,7 +1022,8 @@ TEST_F(OncNetworkParserTest, TestNetworkAndCertificate) {
       std::string(kCertificateWebAuthority) +
       "  ],"
       "}");
-  OncNetworkParser parser(test_blob, NetworkUIData::ONC_SOURCE_USER_IMPORT);
+  OncNetworkParser parser(test_blob, "",
+                          NetworkUIData::ONC_SOURCE_USER_IMPORT);
 
   EXPECT_EQ(1, parser.GetCertificatesSize());
   EXPECT_TRUE(parser.ParseCertificate(0));
diff --git a/chrome/browser/policy/configuration_policy_handler_chromeos.cc b/chrome/browser/policy/configuration_policy_handler_chromeos.cc
index 8c0f1d8ae4be8..ac74293b0c243 100644
--- a/chrome/browser/policy/configuration_policy_handler_chromeos.cc
+++ b/chrome/browser/policy/configuration_policy_handler_chromeos.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -35,7 +35,8 @@ bool NetworkConfigurationPolicyHandler::CheckPolicySettings(
   if (value) {
     std::string onc_blob;
     value->GetAsString(&onc_blob);
-    chromeos::OncNetworkParser parser(onc_blob, onc_source_);
+    // Policy-based ONC blobs cannot have a passphrase.
+    chromeos::OncNetworkParser parser(onc_blob, "", onc_source_);
     if (!parser.parse_error().empty()) {
       errors->AddError(policy_type(),
                        IDS_POLICY_NETWORK_CONFIG_PARSE_ERROR,
diff --git a/crypto/hmac.cc b/crypto/hmac.cc
index 9131313d9e051..7176248732758 100644
--- a/crypto/hmac.cc
+++ b/crypto/hmac.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -8,9 +8,19 @@
 
 #include "base/logging.h"
 #include "crypto/secure_util.h"
+#include "crypto/symmetric_key.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;
+}
+
 size_t HMAC::DigestLength() const {
   switch (hash_alg_) {
     case SHA1:
diff --git a/crypto/hmac.h b/crypto/hmac.h
index b170ce75fa0e4..2e22a15c4fc7b 100644
--- a/crypto/hmac.h
+++ b/crypto/hmac.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -19,6 +19,7 @@ namespace crypto {
 
 // Simplify the interface and reduce includes by abstracting out the internals.
 struct HMACPlatformData;
+class SymmetricKey;
 
 class CRYPTO_EXPORT HMAC {
  public:
@@ -41,6 +42,10 @@ class CRYPTO_EXPORT HMAC {
   // TODO(abarth): key_length should be a size_t.
   bool Init(const unsigned char* key, int key_length) WARN_UNUSED_RESULT;
 
+  // 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;
+
   // 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 {