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)
25 const char kUnableToDecrypt
[] = "Unable to decrypt encrypted ONC";
26 const char kUnableToDecode
[] = "Unable to decode encrypted ONC";
30 const char kEmptyUnencryptedConfiguration
[] =
31 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[],"
32 "\"Certificates\":[]}";
34 scoped_ptr
<base::DictionaryValue
> ReadDictionaryFromJson(
35 const std::string
& json
) {
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
);
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;
54 std::string initial_vector
;
57 std::string stretch_method
;
58 std::string hmac_method
;
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
,
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
) {
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
:
160 case ONC_SOURCE_USER_IMPORT
:
161 return "user import";
163 NOTREACHED() << "unknown ONC source " << source
;