Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: components/os_crypt/os_crypt_linux.cc

Issue 1973483002: OSCrypt for POSIX uses libsecret to store a randomised encryption key. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactored CL Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
vabr (Chromium) 2016/05/13 15:10:18 Looking at the code in this file, I see two main i
cfroussios 2016/05/13 17:09:12 (1) The source of the problem is that OSCrypt is a
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/os_crypt/os_crypt.h" 5 #include "components/os_crypt/os_crypt.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <functional>
9 #include <memory> 10 #include <memory>
10 11
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "components/os_crypt/key_storage_linux.h"
13 #include "crypto/encryptor.h" 15 #include "crypto/encryptor.h"
14 #include "crypto/symmetric_key.h" 16 #include "crypto/symmetric_key.h"
15 17
16 namespace { 18 namespace {
17 19
18 // Salt for Symmetric key derivation. 20 // Salt for Symmetric key derivation.
19 const char kSalt[] = "saltysalt"; 21 const char kSalt[] = "saltysalt";
20 22
21 // Key size required for 128 bit AES. 23 // Key size required for 128 bit AES.
22 const size_t kDerivedKeySizeInBits = 128; 24 const size_t kDerivedKeySizeInBits = 128;
23 25
24 // Constant for Symmetic key derivation. 26 // Constant for Symmetic key derivation.
25 const size_t kEncryptionIterations = 1; 27 const size_t kEncryptionIterations = 1;
26 28
27 // Size of initialization vector for AES 128-bit. 29 // Size of initialization vector for AES 128-bit.
28 const size_t kIVBlockSizeAES128 = 16; 30 const size_t kIVBlockSizeAES128 = 16;
29 31
32 // Used for array indexing
33 enum Version {
34 V10 = 0,
35 V11 = 1,
36 };
37
30 // Prefix for cypher text returned by obfuscation version. We prefix the 38 // Prefix for cypher text returned by obfuscation version. We prefix the
31 // cyphertext with this string so that future data migration can detect 39 // cyphertext with this string so that future data migration can detect
32 // this and migrate to full encryption without data loss. 40 // this and migrate to full encryption without data loss.
33 const char kObfuscationPrefix[] = "v10"; 41 const char* kObfuscationPrefix[] = {
42 "v10", "v11",
43 };
44
45 // Use a mocked key storage and don't try to contact a real service.
46 bool use_mock = false;
vabr (Chromium) 2016/05/13 15:10:19 nit: Please prefix all global variables with g_.
cfroussios 2016/05/13 17:09:12 Done.
47
48 std::unique_ptr<KeyStorageMock> mock;
vabr (Chromium) 2016/05/13 15:10:19 Only plain old data can be a static variable. uniq
cfroussios 2016/05/13 17:09:12 Acknowledged.
49
50 // Lazy acquisition of a KeyStorage. Will be null if no service is found.
51 // Will return a mock if |use_mock| is true.
52 KeyStorage* GetKeyStorage() {
53 if (use_mock) {
54 return mock.get();
55 }
56 static std::unique_ptr<KeyStorage> key_storage(KeyStorage::FindService());
vabr (Chromium) 2016/05/13 15:10:18 Also here, cannot use unique_ptr, because it has a
cfroussios 2016/05/13 17:09:12 Acknowledged.
57 return key_storage.get();
58 }
59
60 // Returns a cached instance of peanuts
61 std::string* GetPasswordV10() {
62 static std::unique_ptr<std::string> password(new std::string("peanuts"));
vabr (Chromium) 2016/05/13 15:10:19 Also here.
cfroussios 2016/05/13 17:09:12 Acknowledged.
63 return password.get();
64 }
65
66 // Caches and returns the password from the KeyStorage or null if there is no
67 // service.
68 // Caching is disabled when mocking.
69 std::string* GetPasswordV11() {
70 if (use_mock)
71 return new std::string(GetKeyStorage()->GetKey());
72
73 static std::unique_ptr<std::string> password(
74 GetKeyStorage() ? new std::string(GetKeyStorage()->GetKey()) : nullptr);
75 return password.get();
76 }
77
78 std::function<std::string*()> get_password[] = {
vabr (Chromium) 2016/05/13 15:10:19 std::function is not yet allowed. http://chromium-
cfroussios 2016/05/13 17:09:12 Acknowledged.
79 &GetPasswordV10, &GetPasswordV11,
80 };
34 81
35 // Generates a newly allocated SymmetricKey object based a hard-coded password. 82 // Generates a newly allocated SymmetricKey object based a hard-coded password.
36 // Ownership of the key is passed to the caller. Returns NULL key if a key 83 // Ownership of the key is passed to the caller. Returns NULL key if a key
37 // generation error occurs. 84 // generation error occurs.
38 crypto::SymmetricKey* GetEncryptionKey() { 85 std::unique_ptr<crypto::SymmetricKey> GetEncryptionKey(Version version) {
39 // We currently "obfuscate" by encrypting and decrypting with hard-coded 86 // We currently "obfuscate" by encrypting and decrypting with hard-coded
40 // password. We need to improve this password situation by moving a secure 87 // password. We need to improve this password situation by moving a secure
41 // password into a system-level key store. 88 // password into a system-level key store.
42 // http://crbug.com/25404 and http://crbug.com/49115 89 // http://crbug.com/25404 and http://crbug.com/49115
43 std::string password = "peanuts";
44 std::string salt(kSalt); 90 std::string salt(kSalt);
45 91
92 std::string* password = get_password[version]();
93 if (password == nullptr)
94 return nullptr;
95
46 // Create an encryption key from our password and salt. 96 // Create an encryption key from our password and salt.
47 std::unique_ptr<crypto::SymmetricKey> encryption_key( 97 std::unique_ptr<crypto::SymmetricKey> encryption_key(
48 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, 98 crypto::SymmetricKey::DeriveKeyFromPassword(
49 password, 99 crypto::SymmetricKey::AES, *password, salt, kEncryptionIterations,
50 salt, 100 kDerivedKeySizeInBits));
51 kEncryptionIterations,
52 kDerivedKeySizeInBits));
53 DCHECK(encryption_key.get()); 101 DCHECK(encryption_key.get());
54 102
55 return encryption_key.release(); 103 return encryption_key;
56 } 104 }
57 105
58 } // namespace 106 } // namespace
59 107
108 // static
60 bool OSCrypt::EncryptString16(const base::string16& plaintext, 109 bool OSCrypt::EncryptString16(const base::string16& plaintext,
61 std::string* ciphertext) { 110 std::string* ciphertext) {
62 return EncryptString(base::UTF16ToUTF8(plaintext), ciphertext); 111 return EncryptString(base::UTF16ToUTF8(plaintext), ciphertext);
63 } 112 }
64 113
114 // static
65 bool OSCrypt::DecryptString16(const std::string& ciphertext, 115 bool OSCrypt::DecryptString16(const std::string& ciphertext,
66 base::string16* plaintext) { 116 base::string16* plaintext) {
67 std::string utf8; 117 std::string utf8;
68 if (!DecryptString(ciphertext, &utf8)) 118 if (!DecryptString(ciphertext, &utf8))
69 return false; 119 return false;
70 120
71 *plaintext = base::UTF8ToUTF16(utf8); 121 *plaintext = base::UTF8ToUTF16(utf8);
72 return true; 122 return true;
73 } 123 }
74 124
125 // static
75 bool OSCrypt::EncryptString(const std::string& plaintext, 126 bool OSCrypt::EncryptString(const std::string& plaintext,
76 std::string* ciphertext) { 127 std::string* ciphertext) {
77 // This currently "obfuscates" by encrypting with hard-coded password. 128 // This currently "obfuscates" by encrypting with hard-coded password.
78 // We need to improve this password situation by moving a secure password 129 // We need to improve this password situation by moving a secure password
79 // into a system-level key store. 130 // into a system-level key store.
80 // http://crbug.com/25404 and http://crbug.com/49115 131 // http://crbug.com/25404 and http://crbug.com/49115
81 132
82 if (plaintext.empty()) { 133 if (plaintext.empty()) {
83 *ciphertext = std::string(); 134 *ciphertext = std::string();
84 return true; 135 return true;
85 } 136 }
86 137
87 std::unique_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey()); 138 // If a KeyStorage is available, use a password backed by the KeyStorage.
139 // Otherwise use the hardcode password.
140 Version version = GetKeyStorage() ? Version::V11 : Version::V10;
141
142 std::unique_ptr<crypto::SymmetricKey> encryption_key(
143 GetEncryptionKey(version));
88 if (!encryption_key.get()) 144 if (!encryption_key.get())
89 return false; 145 return false;
90 146
91 std::string iv(kIVBlockSizeAES128, ' '); 147 std::string iv(kIVBlockSizeAES128, ' ');
92 crypto::Encryptor encryptor; 148 crypto::Encryptor encryptor;
93 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv)) 149 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv))
94 return false; 150 return false;
95 151
96 if (!encryptor.Encrypt(plaintext, ciphertext)) 152 if (!encryptor.Encrypt(plaintext, ciphertext))
97 return false; 153 return false;
98 154
155 // TODO(cfrousios) update with encryption type used
vabr (Chromium) 2016/05/13 15:10:18 nit: Unless this is something planned for the next
cfroussios 2016/05/13 17:09:12 Done.
99 // Prefix the cypher text with version information. 156 // Prefix the cypher text with version information.
100 ciphertext->insert(0, kObfuscationPrefix); 157 ciphertext->insert(0, kObfuscationPrefix[version]);
101 return true; 158 return true;
102 } 159 }
103 160
161 // static
104 bool OSCrypt::DecryptString(const std::string& ciphertext, 162 bool OSCrypt::DecryptString(const std::string& ciphertext,
105 std::string* plaintext) { 163 std::string* plaintext) {
106 // This currently "obfuscates" by encrypting with hard-coded password. 164 // This currently "obfuscates" by encrypting with hard-coded password.
107 // We need to improve this password situation by moving a secure password 165 // We need to improve this password situation by moving a secure password
108 // into a system-level key store. 166 // into a system-level key store.
109 // http://crbug.com/25404 and http://crbug.com/49115 167 // http://crbug.com/25404 and http://crbug.com/49115
110 168
111 if (ciphertext.empty()) { 169 if (ciphertext.empty()) {
112 *plaintext = std::string(); 170 *plaintext = std::string();
113 return true; 171 return true;
114 } 172 }
115 173
116 // Check that the incoming cyphertext was indeed encrypted with the expected 174 // Check that the incoming cyphertext was encrypted and with what version.
117 // version. If the prefix is not found then we'll assume we're dealing with 175 // Credit card numbers are current legacy unencrypted data, so false match
118 // old data saved as clear text and we'll return it directly. 176 // with prefix won't happen.
119 // Credit card numbers are current legacy data, so false match with prefix 177 Version version;
120 // won't happen. 178 if (ciphertext.find(kObfuscationPrefix[Version::V10]) == 0) {
vabr (Chromium) 2016/05/13 15:10:19 Could you use StartsWith from base/strings/string_
cfroussios 2016/05/13 17:09:12 I'm not sure it is more efficient. find runs on th
121 if (ciphertext.find(kObfuscationPrefix) != 0) { 179 version = Version::V10;
180 } else if (ciphertext.find(kObfuscationPrefix[Version::V11]) == 0) {
181 version = Version::V11;
182 } else {
183 // If the prefix is not found then we'll assume we're dealing with
184 // old data saved as clear text and we'll return it directly.
122 *plaintext = ciphertext; 185 *plaintext = ciphertext;
123 return true; 186 return true;
124 } 187 }
125 188
126 // Strip off the versioning prefix before decrypting. 189 // Strip off the versioning prefix before decrypting.
127 std::string raw_ciphertext = ciphertext.substr(strlen(kObfuscationPrefix)); 190 std::string raw_ciphertext =
191 ciphertext.substr(strlen(kObfuscationPrefix[version]));
128 192
129 std::unique_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey()); 193 std::unique_ptr<crypto::SymmetricKey> encryption_key(
194 GetEncryptionKey(version));
130 if (!encryption_key.get()) 195 if (!encryption_key.get())
131 return false; 196 return false;
132 197
133 std::string iv(kIVBlockSizeAES128, ' '); 198 std::string iv(kIVBlockSizeAES128, ' ');
134 crypto::Encryptor encryptor; 199 crypto::Encryptor encryptor;
135 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv)) 200 if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv))
136 return false; 201 return false;
137 202
138 if (!encryptor.Decrypt(raw_ciphertext, plaintext)) 203 if (!encryptor.Decrypt(raw_ciphertext, plaintext))
139 return false; 204 return false;
140 205
141 return true; 206 return true;
142 } 207 }
208
209 // static
210 KeyStorageMock* OSCrypt::UseMockKeyStorage(bool use) {
211 use_mock = use;
212 if (!mock.get())
213 mock.reset(new KeyStorageMock());
214 return mock.get();
215 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698