| // Copyright 2020 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_REPORTING_ENCRYPTION_ENCRYPTION_H_ | |
| #define COMPONENTS_REPORTING_ENCRYPTION_ENCRYPTION_H_ | |
| #include <optional> | |
| #include <string> | |
| #include <string_view> | |
| #include <utility> | |
| #include "base/functional/callback.h" | |
| #include "base/memory/ref_counted.h" | |
| #include "base/memory/scoped_refptr.h" | |
| #include "base/sequence_checker.h" | |
| #include "base/task/sequenced_task_runner.h" | |
| #include "components/reporting/proto/synced/record.pb.h" | |
| #include "components/reporting/util/status.h" | |
| #include "components/reporting/util/statusor.h" | |
| namespace reporting { | |
| // Full implementation of Encryptor, intended for use in reporting client. | |
| // ChaCha20_Poly1305 AEAD encryption of a record in place with symmetric key. | |
| // Curve25519 encryption of the symmetric key with asymmetric public key. | |
| // | |
| // We generate new Curve25519 public/private keys pair for each record. | |
| // Then we produce Curve25519 shared secret from our private key and peer's | |
| // public key, and use it for ChaCha20_Poly1305 AEAD encryption of the record. | |
| // We send out our public value (calling it encrypted symmetric key) together | |
| // with encrypted record. | |
| // | |
| // Upon receiving the encrypted message the peer will produce the same shared | |
| // secret by combining their private key and our public key, and use it as | |
| // a symmetric key for ChaCha20_Poly1305 decryption and validation of the | |
| // record. | |
| // | |
| // Instantiated by a factory: | |
| // StatusOr<scoped_refptr<Encryptor>> Create(); | |
| // The implementation class should never be used directly by the client code. | |
| class Encryptor : public base::RefCountedThreadSafe<Encryptor> { | |
| public: | |
| // Public key id, as defined by Keystore. | |
| using PublicKeyId = int32_t; | |
| // Encryption record handle, which is created by |OpenRecord| and can accept | |
| // pieces of data to be encrypted as one record by calling |AddToRecord| | |
| // multiple times. Resulting encrypted record is available once |CloseRecord| | |
| // is called. | |
| class Handle { | |
| public: | |
| explicit Handle(scoped_refptr<Encryptor> encryptor); | |
| Handle(const Handle& other) = delete; | |
| Handle& operator=(const Handle& other) = delete; | |
| ~Handle(); | |
| // Adds piece of data to the record. | |
| void AddToRecord(std::string_view data, | |
| base::OnceCallback<void(Status)> cb); | |
| // Closes and encrypts the record, hands over the data (encrypted with | |
| // symmetric key) and the key (encrypted with asymmetric key) to be recorded | |
| // by the client (or Status if unsuccessful). Self-destructs after the | |
| // callback. | |
| void CloseRecord(base::OnceCallback<void(StatusOr<EncryptedRecord>)> cb); | |
| private: | |
| // Helper method to compose EncryptedRecord. Called by |CloseRecord| | |
| // as a callback after asynchronous retrieval of the asymmetric key. | |
| void ProduceEncryptedRecord( | |
| base::OnceCallback<void(StatusOr<EncryptedRecord>)> cb, | |
| StatusOr<std::pair<std::string, PublicKeyId>> asymmetric_key_result); | |
| // Accumulated data to encrypt. | |
| std::string record_; | |
| scoped_refptr<Encryptor> encryptor_; | |
| }; | |
| // Factory method to instantiate the Encryptor. | |
| static StatusOr<scoped_refptr<Encryptor>> Create(); | |
| // Factory method creates new record to collect data and encrypt them. | |
| // Hands the Handle raw pointer over to the callback, or error status). | |
| void OpenRecord(base::OnceCallback<void(StatusOr<Handle*>)> cb); | |
| // Delivers public asymmetric key and its id to the implementation. | |
| // To affect specific record, must happen before Handle::CloseRecord | |
| // (it is OK to do it after OpenRecord and Handle::AddToRecord). | |
| // Executes on a sequenced thread, returns with callback. | |
| void UpdateAsymmetricKey(std::string_view new_public_key, | |
| PublicKeyId new_public_key_id, | |
| base::OnceCallback<void(Status)> response_cb); | |
| // Retrieves the current public key. | |
| // Executes on a sequenced thread, returns with callback. | |
| void RetrieveAsymmetricKey( | |
| base::OnceCallback<void(StatusOr<std::pair<std::string, PublicKeyId>>)> | |
| cb); | |
| private: | |
| friend class base::RefCountedThreadSafe<Encryptor>; | |
| Encryptor(); | |
| ~Encryptor(); | |
| // Public key used for asymmetric encryption of symmetric key and its id. | |
| std::optional<std::pair<std::string, PublicKeyId>> asymmetric_key_; | |
| // Sequential task runner for all asymmetric_key_ activities: update, read. | |
| scoped_refptr<base::SequencedTaskRunner> | |
| asymmetric_key_sequenced_task_runner_; | |
| SEQUENCE_CHECKER(asymmetric_key_sequence_checker_); | |
| }; | |
| } // namespace reporting | |
| #endif // COMPONENTS_REPORTING_ENCRYPTION_ENCRYPTION_H_ |