File: encryptor.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (232 lines) | stat: -rw-r--r-- 9,567 bytes parent folder | download | duplicates (5)
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
// Copyright 2023 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_ASYNC_COMMON_ENCRYPTOR_H_
#define COMPONENTS_OS_CRYPT_ASYNC_COMMON_ENCRYPTOR_H_

#include <map>
#include <optional>
#include <string>
#include <vector>

#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "mojo/public/cpp/bindings/default_construct_tag.h"

namespace mojo {
template <typename DataViewType, typename T>
struct StructTraits;
}  // namespace mojo

namespace os_crypt_async {

namespace mojom {
enum class Algorithm;
class EncryptorDataView;
class KeyDataView;
}  // namespace mojom

class EncryptorTestBase;
class OSCryptAsync;
class TestOSCryptAsync;

// This class is used for data encryption. A thread-safe instance can be
// obtained by calling `os_crypt_async::OSCryptAsync::GetInstance`.
class COMPONENT_EXPORT(OS_CRYPT_ASYNC) Encryptor {
 public:
  // A class used by the Encryptor to hold an encryption key and carry out
  // encryption and decryption operations using the specified Algorithm and
  // encryption key.
  class COMPONENT_EXPORT(OS_CRYPT_ASYNC) Key {
   public:
    // Moveable, not copyable.
    Key(Key&& other);
    Key& operator=(Key&& other);
    Key(const Key&) = delete;
    Key& operator=(const Key&) = delete;

    ~Key();

    static constexpr size_t kAES256GCMKeySize = 256u / 8u;
    static constexpr size_t kAES128CBCKeySize = 128u / 8u;

    // Mojo uses this public constructor for serialization.
    explicit Key(mojo::DefaultConstruct::Tag);

    Key(base::span<const uint8_t> key, const mojom::Algorithm& algo);

    bool operator==(const Key& other) const = default;

   private:
    friend class Encryptor;
    // OSCryptAsync and tests need to be able to Clone() keys.
    friend class OSCryptAsync;
    friend class TestOSCryptAsync;
    friend class EncryptorTestBase;
    friend struct mojo::StructTraits<os_crypt_async::mojom::KeyDataView,
                                     os_crypt_async::Encryptor::Key>;
    FRIEND_TEST_ALL_PREFIXES(EncryptorTestWithOSCrypt, MultipleKeys);
    FRIEND_TEST_ALL_PREFIXES(EncryptorTraitsTest, TraitsRoundTrip);

    Key(base::span<const uint8_t> key,
        const mojom::Algorithm& algo,
        bool encrypted);

    std::vector<uint8_t> Encrypt(base::span<const uint8_t> plaintext) const;
    std::optional<std::vector<uint8_t>> Decrypt(
        base::span<const uint8_t> ciphertext) const;

    Key Clone() const;

    // Algorithm. Can only be std::nullopt if the instance is in the process of
    // being serialized to/from mojo.
    std::optional<mojom::Algorithm> algorithm_;
    std::vector<uint8_t> key_;
#if BUILDFLAG(IS_WIN)
    bool encrypted_ = false;
#endif
  };

  enum class Option {
    // No Encryptor options.
    kNone = 0,
    // Indicates that the Encryptor returned should be data-compatible with
    // OSCrypt Sync for both Encrypt and Decrypt operations. Note that Decrypt
    // operations are always backwards compatible with previous Encrypt
    // operations from OSCrypt Sync even if no option is specified: this option
    // only affects the behavior of Encrypt operations.
    kEncryptSyncCompat = 1,
  };

  // Flags that can be set by the Encryptor during a Decrypt call. Pass to a
  // Decrypt operation to obtain these flags.
  struct DecryptFlags {
    // Set by the Encryptor upon success to indicate to the caller that the data
    // that has just been returned from the Decrypt operation should be
    // re-encrypted with a call to Encrypt, as the key has been rotated or a new
    // key is available that provides a different security level.
    bool should_reencrypt = false;

    // Set by the Encryptor upon failure to indicate to the caller that the
    // decryption failed because the key was temporarily unavailable. The
    // failure could be because the key provider temporarily was unable to
    // provide a key, but might be able to provide the key at a later time, e.g.
    // the keychain is temporarily unlocked, or encryption services are
    // temporarily unavailable for another reason. If a failure in decryption
    // occurs and this flag is not set, it can be assumed that the data is not
    // recoverable e.g. the encrypted data is corrupt or the key that encrypted
    // the data has been permanently lost.
    bool temporarily_unavailable = false;
  };

  using KeyRing = std::map</*tag=*/std::string, std::optional<Key>>;

  // Mojo uses this public constructor for serialization.
  explicit Encryptor(mojo::DefaultConstruct::Tag);

  virtual ~Encryptor();

  // Moveable, not copyable.
  Encryptor(Encryptor&& other);
  Encryptor& operator=(Encryptor&& other);
  Encryptor(const Encryptor&) = delete;
  Encryptor& operator=(const Encryptor&) = delete;

  // Encrypt a string with the current Encryptor configuration. This can be
  // called on any thread.
  [[nodiscard]] std::optional<std::vector<uint8_t>> EncryptString(
      const std::string& data) const;

  // Decrypt data previously encrypted using `EncryptData`. This can be called
  // on any thread. If a non-null `flags` is passed, then a set of flags is
  // returned to indicate additional information for the caller. See
  // `DecryptFlags` struct above.
  [[nodiscard]] std::optional<std::string> DecryptData(
      base::span<const uint8_t> data,
      DecryptFlags* flags = nullptr) const;

  // These four APIs are provided for backwards compatibility with OSCrypt. They
  // just call the above functions. For these functions, `flags` is optional.
  [[nodiscard]] bool EncryptString(const std::string& plaintext,
                                   std::string* ciphertext) const;
  [[nodiscard]] bool DecryptString(const std::string& ciphertext,
                                   std::string* plaintext,
                                   DecryptFlags* flags = nullptr) const;
  [[nodiscard]] bool EncryptString16(const std::u16string& plaintext,
                                     std::string* ciphertext) const;
  [[nodiscard]] bool DecryptString16(const std::string& ciphertext,
                                     std::u16string* plaintext,
                                     DecryptFlags* flags = nullptr) const;

  // Returns true if there is at least one key contained within the encryptor
  // that could be used for encryption, otherwise, it will return the value of
  // OSCrypt::IsEncryptionAvailable.
  virtual bool IsEncryptionAvailable() const;

  // Returns true if there is at least one key contained within the encryptor
  // that might be able to decrypt data, otherwise it will return the value of
  // OSCrypt::IsEncryptionAvailable. Note that if this function returns true
  // then there is no guarantee that arbitrary data can be decrypted, as the
  // correct key to decrypt the data might not be available.
  virtual bool IsDecryptionAvailable() const;

 protected:
  // Create an encryptor with a set of `keys`. This is used by the Clone()
  // function and internally by tests. The `provider_for_encryption` specifies
  // which provider is used for encryption, and must have a corresponding key in
  // `keys`. The `provider_for_os_crypt_sync_compatible_encryption` is the
  // filtered version of `provider_for_encryption` that only contains the
  // encryption provider if it's marked itself as being compatible with OSCrypt
  // Sync.
  Encryptor(
      KeyRing keys,
      const std::string& provider_for_encryption,
      const std::string& provider_for_os_crypt_sync_compatible_encryption);

  // Clone is used internally by the factory to vend instances.
  Encryptor Clone(Option option) const;

 private:
  friend class EncryptorTestBase;
  friend class OSCryptAsync;
  friend class TestEncryptor;
  friend struct mojo::StructTraits<os_crypt_async::mojom::EncryptorDataView,
                                   os_crypt_async::Encryptor>;

  FRIEND_TEST_ALL_PREFIXES(EncryptorTraitsTest, TraitsRoundTrip);
  FRIEND_TEST_ALL_PREFIXES(EncryptorTestBase, Clone);

  // Create an encryptor with no keys or encryption provider. In this case, all
  // encryption operations will be delegated to OSCrypt.
  Encryptor();

  // Returns whether `provider_for_encryption_` is set, and it contains an entry
  // in the `keys_` keyring holding a valid key. This means encryption with
  // OSCrypt Async is available.
  bool DefaultEncryptionProviderAvailable() const;

  // A KeyRing consists of a set of provider names and Key values. Encrypted
  // data is always tagged with the provider name and this is used to look up
  // the correct key to use for decryption. This can be empty, meaning
  // encryption will fall back to OSCrypt Sync.
  KeyRing keys_;

  // The provider with this tag is used when encrypting any new data, the Key to
  // use for the encryption is looked up from the entry in the KeyRing. This can
  // be empty string, which means that providers are registered for decryption
  // only, but encryption will fall back to OSCrypt Sync.
  std::string provider_for_encryption_;

  // Provider for OSCrypt Sync compatible encryption. This could be the same as
  // the `provider_for_encryption_` if all keys are OSCrypt compatible, and/or
  // if this Encryptor has been cloned from an Encryptor using the
  // `kEncryptSyncCompat` `Option`.
  std::string provider_for_os_crypt_sync_compatible_encryption_;
};

}  // namespace os_crypt_async

#endif  // COMPONENTS_OS_CRYPT_ASYNC_COMMON_ENCRYPTOR_H_