blob: 6f4552f46bc0a8d3e255cabe8079a49da1aa9626 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MISSIVE_ENCRYPTION_ENCRYPTION_H_
#define MISSIVE_ENCRYPTION_ENCRYPTION_H_
#include <string>
#include <utility>
#include <base/callback.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_refptr.h>
#include <base/optional.h>
#include <base/strings/string_piece.h>
#include "missive/proto/record.pb.h"
#include "missive/util/status.h"
#include "missive/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(base::StringPiece 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(base::StringPiece 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.
base::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 // MISSIVE_ENCRYPTION_ENCRYPTION_H_