[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / chromeos / network / onc / onc_utils.cc
blob85cfe640d90e068d5fc9e790ba03631b2cce55d7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/onc/onc_utils.h"
7 #include "base/base64.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/values.h"
11 #include "chromeos/network/network_event_log.h"
12 #include "chromeos/network/onc/onc_constants.h"
13 #include "crypto/encryptor.h"
14 #include "crypto/hmac.h"
15 #include "crypto/symmetric_key.h"
17 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
18 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
20 namespace chromeos {
21 namespace onc {
23 namespace {
25 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
26 const char kUnableToDecode[] = "Unable to decode encrypted ONC";
28 } // namespace
30 const char kEmptyUnencryptedConfiguration[] =
31 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[],"
32 "\"Certificates\":[]}";
34 scoped_ptr<base::DictionaryValue> ReadDictionaryFromJson(
35 const std::string& json) {
36 std::string error;
37 base::Value* root = base::JSONReader::ReadAndReturnError(
38 json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error);
40 base::DictionaryValue* dict_ptr = NULL;
41 if (!root || !root->GetAsDictionary(&dict_ptr)) {
42 ONC_LOG_ERROR("Invalid JSON Dictionary: " + error);
43 delete root;
46 return make_scoped_ptr(dict_ptr);
49 scoped_ptr<base::DictionaryValue> Decrypt(const std::string& passphrase,
50 const base::DictionaryValue& root) {
51 const int kKeySizeInBits = 256;
52 const int kMaxIterationCount = 500000;
53 std::string onc_type;
54 std::string initial_vector;
55 std::string salt;
56 std::string cipher;
57 std::string stretch_method;
58 std::string hmac_method;
59 std::string hmac;
60 int iterations;
61 std::string ciphertext;
63 if (!root.GetString(encrypted::kCiphertext, &ciphertext) ||
64 !root.GetString(encrypted::kCipher, &cipher) ||
65 !root.GetString(encrypted::kHMAC, &hmac) ||
66 !root.GetString(encrypted::kHMACMethod, &hmac_method) ||
67 !root.GetString(encrypted::kIV, &initial_vector) ||
68 !root.GetInteger(encrypted::kIterations, &iterations) ||
69 !root.GetString(encrypted::kSalt, &salt) ||
70 !root.GetString(encrypted::kStretch, &stretch_method) ||
71 !root.GetString(kType, &onc_type) ||
72 onc_type != kEncryptedConfiguration) {
74 ONC_LOG_ERROR("Encrypted ONC malformed.");
75 return scoped_ptr<base::DictionaryValue>();
78 if (hmac_method != encrypted::kSHA1 ||
79 cipher != encrypted::kAES256 ||
80 stretch_method != encrypted::kPBKDF2) {
81 ONC_LOG_ERROR("Encrypted ONC unsupported encryption scheme.");
82 return scoped_ptr<base::DictionaryValue>();
85 // Make sure iterations != 0, since that's not valid.
86 if (iterations == 0) {
87 ONC_LOG_ERROR(kUnableToDecrypt);
88 return scoped_ptr<base::DictionaryValue>();
91 // Simply a sanity check to make sure we can't lock up the machine
92 // for too long with a huge number (or a negative number).
93 if (iterations < 0 || iterations > kMaxIterationCount) {
94 ONC_LOG_ERROR("Too many iterations in encrypted ONC");
95 return scoped_ptr<base::DictionaryValue>();
98 if (!base::Base64Decode(salt, &salt)) {
99 ONC_LOG_ERROR(kUnableToDecode);
100 return scoped_ptr<base::DictionaryValue>();
103 scoped_ptr<crypto::SymmetricKey> key(
104 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
105 passphrase,
106 salt,
107 iterations,
108 kKeySizeInBits));
110 if (!base::Base64Decode(initial_vector, &initial_vector)) {
111 ONC_LOG_ERROR(kUnableToDecode);
112 return scoped_ptr<base::DictionaryValue>();
114 if (!base::Base64Decode(ciphertext, &ciphertext)) {
115 ONC_LOG_ERROR(kUnableToDecode);
116 return scoped_ptr<base::DictionaryValue>();
118 if (!base::Base64Decode(hmac, &hmac)) {
119 ONC_LOG_ERROR(kUnableToDecode);
120 return scoped_ptr<base::DictionaryValue>();
123 crypto::HMAC hmac_verifier(crypto::HMAC::SHA1);
124 if (!hmac_verifier.Init(key.get()) ||
125 !hmac_verifier.Verify(ciphertext, hmac)) {
126 ONC_LOG_ERROR(kUnableToDecrypt);
127 return scoped_ptr<base::DictionaryValue>();
130 crypto::Encryptor decryptor;
131 if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector)) {
132 ONC_LOG_ERROR(kUnableToDecrypt);
133 return scoped_ptr<base::DictionaryValue>();
136 std::string plaintext;
137 if (!decryptor.Decrypt(ciphertext, &plaintext)) {
138 ONC_LOG_ERROR(kUnableToDecrypt);
139 return scoped_ptr<base::DictionaryValue>();
142 scoped_ptr<base::DictionaryValue> new_root =
143 ReadDictionaryFromJson(plaintext);
144 if (new_root.get() == NULL) {
145 ONC_LOG_ERROR("Property dictionary malformed.");
146 return scoped_ptr<base::DictionaryValue>();
149 return new_root.Pass();
152 std::string GetSourceAsString(ONCSource source) {
153 switch (source) {
154 case ONC_SOURCE_DEVICE_POLICY:
155 return "device policy";
156 case ONC_SOURCE_USER_POLICY:
157 return "user policy";
158 case ONC_SOURCE_NONE:
159 return "none";
160 case ONC_SOURCE_USER_IMPORT:
161 return "user import";
163 NOTREACHED() << "unknown ONC source " << source;
164 return "unknown";
167 } // chromeos
168 } // onc