1 // Copyright 2020 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 CHROME_BROWSER_POLICY_MESSAGING_LAYER_ENCRYPTION_DECRYPTION_H_
6 #define CHROME_BROWSER_POLICY_MESSAGING_LAYER_ENCRYPTION_DECRYPTION_H_
7 
8 #include <string>
9 
10 #include "base/callback.h"
11 #include "base/containers/flat_map.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_refptr.h"
14 #include "base/optional.h"
15 #include "base/strings/string_piece.h"
16 #include "base/threading/thread.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "chrome/browser/policy/messaging_layer/encryption/encryption.h"
19 #include "chrome/browser/policy/messaging_layer/util/status.h"
20 #include "chrome/browser/policy/messaging_layer/util/statusor.h"
21 
22 namespace reporting {
23 
24 // Full implementation of Decryptor, intended for use in tests and potentially
25 // in reporting server (wrapped in a Java class).
26 //
27 // Curve25519 decryption of the symmetric key with asymmetric private key.
28 // ChaCha20_Poly1305 decryption and verification of a record in place with
29 // symmetric key.
30 //
31 // Instantiated by an implementation-specific factory:
32 //   StatusOr<scoped_refptr<Decryptor>> Create();
33 class Decryptor : public base::RefCountedThreadSafe<Decryptor> {
34  public:
35   // Decryption record handle, which is created by |OpenRecord| and can accept
36   // pieces of data to be decrypted as one record by calling |AddToRecord|
37   // multiple times. Resulting decrypted record is available once |CloseRecord|
38   // is called.
39   class Handle {
40    public:
41     Handle(base::StringPiece shared_secret, scoped_refptr<Decryptor> decryptor);
42     Handle(const Handle& other) = delete;
43     Handle& operator=(const Handle& other) = delete;
44     ~Handle();
45 
46     // Adds piece of encrypted data to the record.
47     void AddToRecord(base::StringPiece data,
48                      base::OnceCallback<void(Status)> cb);
49 
50     // Closes and attempts to decrypt the record. Hands over the decrypted data
51     // to be processed by the server (or Status if unsuccessful). Accesses key
52     // store to attempt all private keys that are considered to be valid,
53     // starting with the one that matches the hash. Self-destructs after the
54     // callback.
55     void CloseRecord(base::OnceCallback<void(StatusOr<base::StringPiece>)> cb);
56 
57    private:
58     // Shared secret based on which symmetric key is produced.
59     const std::string shared_secret_;
60 
61     // Accumulated data to decrypt.
62     std::string record_;
63 
64     scoped_refptr<Decryptor> decryptor_;
65   };
66 
67   // Factory method to instantiate the Decryptor.
68   static StatusOr<scoped_refptr<Decryptor>> Create();
69 
70   // Factory method creates a new record to collect data and decrypt them with
71   // the given encrypted key. Hands the handle raw pointer over to the callback,
72   // or error status.
73   void OpenRecord(base::StringPiece encrypted_key,
74                   base::OnceCallback<void(StatusOr<Handle*>)> cb);
75 
76   // Recreates shared secret from local private key and peer public value and
77   // returns it or error status.
78   StatusOr<std::string> DecryptSecret(base::StringPiece public_key,
79                                       base::StringPiece peer_public_value);
80 
81   // Records a key pair (stores only private key).
82   // Executes on a sequenced thread, returns key id or error with callback.
83   void RecordKeyPair(
84       base::StringPiece private_key,
85       base::StringPiece public_key,
86       base::OnceCallback<void(StatusOr<Encryptor::PublicKeyId>)> cb);
87 
88   // Retrieves private key matching the public key hash.
89   // Executes on a sequenced thread, returns with callback.
90   void RetrieveMatchingPrivateKey(
91       Encryptor::PublicKeyId public_key_id,
92       base::OnceCallback<void(StatusOr<std::string>)> cb);
93 
94  private:
95   friend base::RefCountedThreadSafe<Decryptor>;
96   Decryptor();
97   ~Decryptor();
98 
99   // Map of hash(public_key)->{private key, time stamp}
100   // Private key is located by the hash of a public key, sent together with the
101   // encrypted record. Keys older than pre-defined threshold are discarded.
102   // Time stamp allows to drop outdated keys (not implemented yet).
103   struct KeyInfo {
104     std::string private_key;
105     base::Time time_stamp;
106   };
107   base::flat_map<Encryptor::PublicKeyId, KeyInfo> keys_;
108 
109   // Sequential task runner for all keys_ activities:
110   // recording, lookup, purge.
111   scoped_refptr<base::SequencedTaskRunner> keys_sequenced_task_runner_;
112 
113   SEQUENCE_CHECKER(keys_sequence_checker_);
114 };
115 
116 }  // namespace reporting
117 
118 #endif  // CHROME_BROWSER_POLICY_MESSAGING_LAYER_ENCRYPTION_DECRYPTION_H_
119