1 // Copyright 2019 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.
4 
5 #ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_BUNDLE_H_
6 #define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_BUNDLE_H_
7 
8 #include "base/containers/flat_map.h"
9 #include "base/containers/flat_set.h"
10 #include "base/optional.h"
11 #include "base/values.h"
12 #include "chromeos/services/device_sync/cryptauth_key.h"
13 #include "chromeos/services/device_sync/proto/cryptauth_directive.pb.h"
14 
15 namespace chromeos {
16 
17 namespace device_sync {
18 
19 // A group of related CryptAuthKeys, uniquely identified by their handles.
20 //
21 // No more than one key in the bundle can be active at a time, and only the
22 // active key should be used for encryption, signing, etc. Inactive keys are
23 // retained and can be activated in the future, for example, due to a
24 // SyncSingleKeyResponse::KeyAction sent by CryptAuth.
25 //
26 // All key bundles used in Chrome OS are enumerated in the Name enum class. The
27 // name string corresponding to each enum value can be retrieved via
28 // KeyBundleNameEnumToString(). For key bundles that enroll with CryptAuth, this
29 // string is used to populate the SyncSingleKeysRequest::key_name protobuf
30 // field.
31 class CryptAuthKeyBundle {
32  public:
33   // Names that uniquely define a CryptAuthKeyBundle.
34   enum class Name {
35     // A non-rotated asymmetric key associated with a user on the device. It is
36     // used for encrypting device-to-device communications, for example, and it
37     // has historically been used as a device identifier.
38     kUserKeyPair,
39     // Currently unused but required for CryptAuth v2 Enrollment.
40     kLegacyAuthzenKey,
41     // Enrolling this asymmetric key adds the device to the user's DeviceSync v2
42     // "DeviceSync:BetterTogether" group. This key is not to be confused with
43     // the unenrolled kDeviceSyncBetterTogetherGroupKey.
44     kDeviceSyncBetterTogether,
45     // A key pair that does *not* enroll with CryptAuth, used to encrypt and
46     // decrypt the metadata of all devices in the user's
47     // "DeviceSync:BetterTogether" group. This metadata is passed in an
48     // end-to-end encrypted fashion via DeviceSync v2 SyncMetadata calls .
49     kDeviceSyncBetterTogetherGroupKey
50   };
51 
52   // Returns all Name enum values as a set.
53   static const base::flat_set<CryptAuthKeyBundle::Name>& AllNames();
54 
55   // Returns the Name enum value of all key bundles that enroll with CryptAuth.
56   static const base::flat_set<CryptAuthKeyBundle::Name>& AllEnrollableNames();
57 
58   static std::string KeyBundleNameEnumToString(CryptAuthKeyBundle::Name name);
59   static base::Optional<CryptAuthKeyBundle::Name> KeyBundleNameStringToEnum(
60       const std::string& name);
61 
62   static base::Optional<CryptAuthKeyBundle> FromDictionary(
63       const base::Value& dict);
64 
65   CryptAuthKeyBundle(Name name);
66 
67   CryptAuthKeyBundle(const CryptAuthKeyBundle&);
68 
69   ~CryptAuthKeyBundle();
70 
name()71   Name name() const { return name_; }
72 
handle_to_key_map()73   const base::flat_map<std::string, CryptAuthKey>& handle_to_key_map() const {
74     return handle_to_key_map_;
75   }
76 
key_directive()77   const base::Optional<cryptauthv2::KeyDirective>& key_directive() const {
78     return key_directive_;
79   }
80 
set_key_directive(const cryptauthv2::KeyDirective & key_directive)81   void set_key_directive(const cryptauthv2::KeyDirective& key_directive) {
82     key_directive_ = key_directive;
83   }
84 
85   // Returns nullptr if there is no active key.
86   const CryptAuthKey* GetActiveKey() const;
87 
88   // If the key being added is active, all other keys in the bundle will be
89   // deactivated. If the handle of the input key matches one in the bundle, the
90   // existing key will be overwritten.
91   // Note: All keys added to the bundle kUserKeyPair must have the handle
92   // kCryptAuthFixedUserKeyPairHandle.
93   void AddKey(const CryptAuthKey& key);
94 
95   // Activates the key corresponding to |handle| in the bundle and deactivates
96   // the other keys.
97   void SetActiveKey(const std::string& handle);
98 
99   // Sets all key statuses to kInactive.
100   void DeactivateKeys();
101 
102   // Remove the key corresponding to |handle| from the bundle.
103   void DeleteKey(const std::string& handle);
104 
105   base::Value AsDictionary() const;
106 
107   bool operator==(const CryptAuthKeyBundle& other) const;
108   bool operator!=(const CryptAuthKeyBundle& other) const;
109 
110  private:
111   Name name_;
112   base::flat_map<std::string, CryptAuthKey> handle_to_key_map_;
113   base::Optional<cryptauthv2::KeyDirective> key_directive_;
114 };
115 
116 }  // namespace device_sync
117 
118 }  // namespace chromeos
119 
120 #endif  // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_BUNDLE_H_
121