File: os_crypt.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (313 lines) | stat: -rw-r--r-- 12,630 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_OS_CRYPT_SYNC_OS_CRYPT_H_
#define COMPONENTS_OS_CRYPT_SYNC_OS_CRYPT_H_

#include <array>
#include <memory>
#include <optional>
#include <string>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "crypto/subtle_passkey.h"

#if BUILDFLAG(IS_APPLE)
namespace crypto {
class AppleKeychain;
}
#endif

#if BUILDFLAG(IS_LINUX)
class KeyStorageLinux;
#endif  // BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_WIN)
class PrefRegistrySimple;
class PrefService;
#endif  // BUILDFLAG(IS_WIN)

namespace os_crypt {
struct Config;
}

// Temporary interface due to OSCrypt refactor. See OSCryptImpl for descriptions
// of what each function does.
namespace OSCrypt {
#if BUILDFLAG(IS_LINUX)
COMPONENT_EXPORT(OS_CRYPT)
void SetConfig(std::unique_ptr<os_crypt::Config> config);
#endif  // BUILDFLAG(IS_LINUX)
COMPONENT_EXPORT(OS_CRYPT) bool IsEncryptionAvailable();
COMPONENT_EXPORT(OS_CRYPT)
bool EncryptString16(const std::u16string& plaintext, std::string* ciphertext);
COMPONENT_EXPORT(OS_CRYPT)
bool DecryptString16(const std::string& ciphertext, std::u16string* plaintext);
COMPONENT_EXPORT(OS_CRYPT)
bool EncryptString(const std::string& plaintext, std::string* ciphertext);
COMPONENT_EXPORT(OS_CRYPT)
bool DecryptString(const std::string& ciphertext, std::string* plaintext);
#if BUILDFLAG(IS_WIN)
COMPONENT_EXPORT(OS_CRYPT)
void RegisterLocalPrefs(PrefRegistrySimple* registry);
COMPONENT_EXPORT(OS_CRYPT) bool Init(PrefService* local_state);

// Initialises OSCryptImpl using an encryption key present in the |local_state|.
// It is similar to the Init() method above, however, it will not create
// a new encryption key if it is not present in the |local_state|.
enum InitResult {
  kSuccess,
  kKeyDoesNotExist,
  kInvalidKeyFormat,
  kDecryptionFailed
};

COMPONENT_EXPORT(OS_CRYPT)
InitResult InitWithExistingKey(PrefService* local_state);
#endif  // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_APPLE)
COMPONENT_EXPORT(OS_CRYPT) void UseMockKeychainForTesting(bool use_mock);
COMPONENT_EXPORT(OS_CRYPT)
void UseLockedMockKeychainForTesting(bool use_locked);
#endif  // BUILDFLAG(IS_APPLE)
COMPONENT_EXPORT(OS_CRYPT)
std::string GetRawEncryptionKey();
COMPONENT_EXPORT(OS_CRYPT)
void SetRawEncryptionKey(const std::string& key);
#if BUILDFLAG(IS_WIN)
COMPONENT_EXPORT(OS_CRYPT) void UseMockKeyForTesting(bool use_mock);
COMPONENT_EXPORT(OS_CRYPT) void SetLegacyEncryptionForTesting(bool legacy);
COMPONENT_EXPORT(OS_CRYPT) void ResetStateForTesting();
#endif  // BUILDFLAG(IS_WIN)
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
COMPONENT_EXPORT(OS_CRYPT)
void UseMockKeyStorageForTesting(
    base::OnceCallback<std::unique_ptr<KeyStorageLinux>()>
        storage_provider_factory);
COMPONENT_EXPORT(OS_CRYPT) void ClearCacheForTesting();
COMPONENT_EXPORT(OS_CRYPT)
void SetEncryptionPasswordForTesting(const std::string& password);
#endif  // (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) &&         \
        !(BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) || \
    BUILDFLAG(IS_FUCHSIA)
COMPONENT_EXPORT(OS_CRYPT)
void SetEncryptionAvailableForTesting(std::optional<bool> available);
#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !(BUILDFLAG(IS_LINUX)
        // && !BUILDFLAG(IS_CASTOS)) || BUILDFLAG(IS_FUCHSIA)
}  // namespace OSCrypt

// The OSCryptImpl class gives access to simple encryption and decryption of
// strings. Note that on Mac, access to the system Keychain is required and
// these calls can block the current thread to collect user input. The same is
// true for Linux, if a password management tool is available.
class COMPONENT_EXPORT(OS_CRYPT) OSCryptImpl {
 public:
  OSCryptImpl();
  ~OSCryptImpl();
  OSCryptImpl(const OSCryptImpl&) = delete;
  OSCryptImpl(OSCryptImpl&&) = delete;
  OSCryptImpl& operator=(const OSCryptImpl&) = delete;
  OSCryptImpl& operator=(OSCryptImpl&&) = delete;

  // Returns singleton instance of OSCryptImpl.
  static OSCryptImpl* GetInstance();

#if BUILDFLAG(IS_LINUX)
  // Set the configuration of OSCryptImpl.
  // This method, or SetRawEncryptionKey(), must be called before using
  // EncryptString() and DecryptString().
  void SetConfig(std::unique_ptr<os_crypt::Config> config);
#endif  // BUILDFLAG(IS_LINUX)

  // In production code:
  // - On Linux, returns true iff the real secret key (not hardcoded one) is
  //   available.
  // - On MacOS, returns true if Keychain is available (for mock Keychain it
  //   returns true if not using locked Keychain, false if using locked mock
  //   Keychain).
  // - On Windows, returns true if non mock encryption key is available.
  // - On other platforms, returns true as OSCryptImpl will use a hardcoded key.
  //
  // Tests may override the above behavior.
  bool IsEncryptionAvailable();

  // Encrypt a string16. The output (second argument) is really an array of
  // bytes, but we're passing it back as a std::string.
  bool EncryptString16(const std::u16string& plaintext,
                       std::string* ciphertext);

  // Decrypt an array of bytes obtained with EncryptString16 back into a
  // string16. Note that the input (first argument) is a std::string, so you
  // need to first get your (binary) data into a string.
  bool DecryptString16(const std::string& ciphertext,
                       std::u16string* plaintext);

  // Encrypt a string.
  bool EncryptString(const std::string& plaintext, std::string* ciphertext);

  // Decrypt an array of bytes obtained with EnctryptString back into a string.
  // Note that the input (first argument) is a std::string, so you need to first
  // get your (binary) data into a string.
  bool DecryptString(const std::string& ciphertext, std::string* plaintext);

#if BUILDFLAG(IS_WIN)
  // Registers preferences used by OSCryptImpl.
  static void RegisterLocalPrefs(PrefRegistrySimple* registry);

  // Initialises OSCryptImpl.
  // This method should be called on the main UI thread before any calls to
  // encryption or decryption. Returns |true| if os_crypt successfully
  // initialized.
  bool Init(PrefService* local_state);

  // Initialises OSCryptImpl using an encryption key present in the
  // |local_state|. It is similar to the Init() method above, however, it will
  // not create a new encryption key if it is not present in the |local_state|.

  OSCrypt::InitResult InitWithExistingKey(PrefService* local_state);
#endif

#if BUILDFLAG(IS_APPLE)
  // For unit testing purposes we instruct the Encryptor to use a mock Keychain
  // on the Mac. The default is to use the real Keychain. Use OSCryptMocker,
  // instead of calling this method directly.
  void UseMockKeychainForTesting(bool use_mock);

  // When Keychain is locked, it's not possible to get the encryption key. This
  // is used only for testing purposes. Enabling locked Keychain also enables
  // mock Keychain. Use OSCryptMocker, instead of calling this method directly.
  void UseLockedMockKeychainForTesting(bool use_locked);
#endif

  // Get the raw encryption key to be used for all AES encryption. The result
  // can be used to call SetRawEncryptionKey() in another process. Returns an
  // empty string in some situations, for example:
  // - password access is denied
  // - key generation error
  // - if a hardcoded password is used instead of a random per-user key
  // This method is thread-safe.
  std::string GetRawEncryptionKey();

  // Set the raw encryption key to be used for all AES encryption.
  // On platforms that may use a hardcoded key, |key| can be empty and
  // OSCryptImpl will default to the hardcoded key. This method is thread-safe.
  void SetRawEncryptionKey(const std::string& key);

#if BUILDFLAG(IS_WIN)
  // For unit testing purposes we instruct the Encryptor to use a mock Key. The
  // default is to use the real Key bound to profile. Use OSCryptMocker, instead
  // of calling this method directly.
  void UseMockKeyForTesting(bool use_mock);

  // For unit testing purposes, encrypt data using the older DPAPI method rather
  // than using a session key.
  void SetLegacyEncryptionForTesting(bool legacy);

  // For unit testing purposes, reset the state of OSCryptImpl so a new key can
  // be loaded via Init() or SetRawEncryptionkey().
  void ResetStateForTesting();
#endif

#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
  // For unit testing purposes, inject methods to be used.
  // |storage_provider_factory| provides the desired |KeyStorage|
  // implementation. If the provider returns |nullptr|, a hardcoded password
  // will be used. If |storage_provider_factory| is null callback, restores the
  // real implementation.
  void UseMockKeyStorageForTesting(
      base::OnceCallback<std::unique_ptr<KeyStorageLinux>()>
          storage_provider_factory);

  // Clears any caching and most lazy initialisations performed by the
  // production code. Should be used after any test which required a password.
  void ClearCacheForTesting();

  // Sets the password with which the encryption key is derived, e.g. "peanuts".
  void SetEncryptionPasswordForTesting(const std::string& password);
#endif  // (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
 private:
#if BUILDFLAG(IS_APPLE)
  // Return the keychain to use for accessing the encryption key.
  std::unique_ptr<crypto::AppleKeychain> GetKeychain() const;

  // Derives an encryption key from data stored in the keychain if necessary.
  // Returns true if there is an encryption key available and false otherwise.
  bool DeriveKey();
#endif  // BUILDFLAG(IS_APPLE)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_APPLE)
  // This lock is used to make the GetEncryptionKey and
  // GetRawEncryptionKey methods thread-safe.
  static base::Lock& GetLock();
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_APPLE)

#if BUILDFLAG(IS_LINUX)
  static constexpr size_t kDerivedKeyBytes = 16;

  crypto::SubtlePassKey MakeCryptoPassKey();

  // Derive a new key of `kDerivedKeyBytes` from a given input key using
  // PBKDF2-HMAC-SHA1.
  std::array<uint8_t, kDerivedKeyBytes> Pbkdf2(const std::string& key);

  // Try to fill in `v11_key_` with a V1.1 derived key. Returns true if a v11
  // key is now present in `v11_key_` (which may have just been cached
  // previously) and false if one is not present. If `try_v11_` is false, and
  // there is no cached v11 key, this method just returns false.
  bool DeriveV11Key();

  // The cached V1.1 derived key. If this is nullopt, no V1.1 key is available
  // yet, but `DeriveV11Key()` may be able to generate one.
  std::optional<std::array<uint8_t, kDerivedKeyBytes>> v11_key_;

  // Whether to try V1.1 key generation at all. When OSCrypt is used in the
  // network service, V1.1 key generation can't succeed (it is blocked by the
  // sandbox) so it should never be attempted.
  bool try_v11_ = true;

  // |config_| is used to initialise |password_v11_cache_| and then cleared.
  std::unique_ptr<os_crypt::Config> config_;

  base::OnceCallback<std::unique_ptr<KeyStorageLinux>()>
      storage_provider_factory_for_testing_;
#endif  // BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_WIN)
  // Use mock key instead of a real encryption key. Used for testing.
  bool use_mock_key_ = false;

  // Store data using the legacy (DPAPI) method rather than session key.
  bool use_legacy_ = false;

  // Encryption Key. Set either by calling Init() or SetRawEncryptionKey().
  std::string encryption_key_;

  // Mock Encryption Key. Only set and used if use_mock_key_ is true.
  std::string mock_encryption_key_;
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_APPLE)
  // `try_keychain_` indicates whether this object should try using the keychain
  // (which may itself be mocked out) to derive an encryption key; it can be
  // false even if `key_present_` is also false because this object will only
  // try using the keychain at most once and if the first use fails it will
  // persistently fail to decrypt.
  bool try_keychain_ = true;

  static constexpr size_t kDerivedKeySize = 16;
  std::optional<std::array<uint8_t, kDerivedKeySize>> key_;
  // TODO(crbug.com/389737048): Refactor to allow dependency injection of Keychain.
  bool use_mock_keychain_ = false;
  // This flag is used to make the GetEncryptionKey method return NULL if used
  // along with mock Keychain.
  bool use_locked_mock_keychain_ = false;
#endif
};

#endif  // COMPONENTS_OS_CRYPT_SYNC_OS_CRYPT_H_