blob: 99299ae9648498bce6d02bd113737d1432731650 [file] [log] [blame]
// Copyright 2015 The Chromium 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 CHROMEOS_SERVICES_SECURE_CHANNEL_DEVICE_TO_DEVICE_INITIATOR_HELPER_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_DEVICE_TO_DEVICE_INITIATOR_HELPER_H_
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/services/device_sync/proto/securemessage.pb.h"
#include "chromeos/services/secure_channel/session_keys.h"
namespace cryptauth {
class SecureMessageDelegate;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
// Class containing operations in the DeviceToDevice protocol that the initiator
// needs to perform. This class is instantiable rather than being a utility
// class because it relies on a WeakPtrFactory to prevent referencing deleted
// memory.
//
// All operations are asynchronous because we use the SecureMessageDelegate for
// crypto operations, whose implementation may be asynchronous.
//
// In the DeviceToDevice protocol, the initiator needs to send two messages to
// the responder and parse one message from the responder:
// 1. Send [Hello] Message
// This message contains a public key that the initiator generates for the
// current session. This message is signed by the long term symmetric key.
// 2. Parse [Responder Auth] Message
// The responder parses [Hello] and sends this message, which contains the
// responder's session public key. This message also contains sufficient
// information for the initiator to authenticate the responder.
// 3. Send [Initiator Auth] Message
// After receiving the responder's session public key, the initiator crafts
// and sends this message so the responder can authenticate the initiator.
class DeviceToDeviceInitiatorHelper {
public:
// Callback for operations that create a message. Invoked with the serialized
// SecureMessage upon success or the empty string upon failure.
typedef base::Callback<void(const std::string&)> MessageCallback;
// Callback for ValidateResponderAuthMessage. The first argument will be
// called with the validation outcome. If validation succeeded, then the
// second argument will contain the session symmetric key derived from the
// [Responder Auth] message.
typedef base::Callback<void(bool, const SessionKeys&)>
ValidateResponderAuthCallback;
DeviceToDeviceInitiatorHelper();
virtual ~DeviceToDeviceInitiatorHelper();
// Creates the [Hello] message, which is the first message that is sent:
// |session_public_key|: This session public key will be stored in plaintext
// (but signed) so the responder can parse it.
// |persistent_symmetric_key|: The long-term symmetric key that is shared by
// the initiator and responder.
// |secure_message_delegate|: Delegate for SecureMessage operations. This
// instance is not owned, and must live until after |callback| is invoked.
// |callback|: Invoked upon operation completion with the serialized message
// or an empty string.
void CreateHelloMessage(
const std::string& session_public_key,
const std::string& persistent_symmetric_key,
cryptauth::SecureMessageDelegate* secure_message_delegate,
const MessageCallback& callback);
// Validates that the [Responder Auth] message, received from the responder,
// is properly signed and encrypted.
// |responder_auth_message|: The bytes of the [Responder Auth] message to
// validate.
// |persistent_responder_public_key|: The long-term public key possessed by
// the responder device.
// |persistent_symmetric_key|: The long-term symmetric key that is shared by
// the initiator and responder.
// |session_private_key|: The session private key is used in an Diffie-Helmann
// key exchange once the responder public key is extracted. The derived
// session symmetric key is used in the validation process.
// |hello_message|: The initial [Hello] message that was sent, which is used
// in the signature calculation.
// |secure_message_delegate|: Delegate for SecureMessage operations. This
// instance is not owned, and must live until after |callback| is invoked.
// |callback|: Invoked upon operation completion with whether
// |responder_auth_message| is validated successfully.
void ValidateResponderAuthMessage(
const std::string& responder_auth_message,
const std::string& persistent_responder_public_key,
const std::string& persistent_symmetric_key,
const std::string& session_private_key,
const std::string& hello_message,
cryptauth::SecureMessageDelegate* secure_message_delegate,
const ValidateResponderAuthCallback& callback);
// Creates the [Initiator Auth] message, which allows the responder to
// authenticate the initiator:
// |session_keys|: The session symmetric keys.
// |persistent_symmetric_key|: The long-term symmetric key that is shared by
// the initiator and responder.
// |responder_auth_message|: The [Responder Auth] message sent previously to
// the responder. These bytes are used in the signature calculation.
// |secure_message_delegate|: Delegate for SecureMessage operations. This
// instance is not owned, and must live until after |callback| is invoked.
// |callback|: Invoked upon operation completion with the serialized message
// or an empty string.
void CreateInitiatorAuthMessage(
const SessionKeys& session_keys,
const std::string& persistent_symmetric_key,
const std::string& responder_auth_message,
cryptauth::SecureMessageDelegate* secure_message_delegate,
const MessageCallback& callback);
private:
// Helper struct containing all the context needed to validate the
// [Responder Auth] message.
struct ValidateResponderAuthMessageContext {
ValidateResponderAuthMessageContext(
const std::string& responder_auth_message,
const std::string& persistent_responder_public_key,
const std::string& persistent_symmetric_key,
const std::string& session_private_key,
const std::string& hello_message,
cryptauth::SecureMessageDelegate* secure_message_delegate,
const ValidateResponderAuthCallback& callback);
ValidateResponderAuthMessageContext(
const ValidateResponderAuthMessageContext& other);
~ValidateResponderAuthMessageContext();
std::string responder_auth_message;
std::string persistent_responder_public_key;
std::string persistent_symmetric_key;
std::string session_private_key;
std::string hello_message;
cryptauth::SecureMessageDelegate* secure_message_delegate;
ValidateResponderAuthCallback callback;
std::string responder_session_public_key;
std::string session_symmetric_key;
};
// Begins the [Responder Auth] validation flow by validating the header.
void BeginResponderAuthValidation(
ValidateResponderAuthMessageContext context);
// Called after the session symmetric key is derived, so now we can unwrap the
// outer message of [Responder Auth].
void OnSessionSymmetricKeyDerived(ValidateResponderAuthMessageContext context,
const std::string& session_symmetric_key);
// Called after the outer-most layer of [Responder Auth] is unwrapped.
void OnOuterMessageUnwrappedForResponderAuth(
const ValidateResponderAuthMessageContext& context,
bool verified,
const std::string& payload,
const securemessage::Header& header);
// Called after the middle layer of [Responder Auth] is unwrapped.
void OnMiddleMessageUnwrappedForResponderAuth(
const ValidateResponderAuthMessageContext& context,
bool verified,
const std::string& payload,
const securemessage::Header& header);
// Called after inner message is created.
void OnInnerMessageCreatedForInitiatorAuth(
const SessionKeys& session_keys,
cryptauth::SecureMessageDelegate* secure_message_delegate,
const DeviceToDeviceInitiatorHelper::MessageCallback& callback,
const std::string& inner_message);
// Callback for CreateInitiatorAuthMessage(), after the inner message is
// created.
void OnInnerMessageUnwrappedForResponderAuth(
const ValidateResponderAuthMessageContext& context,
bool verified,
const std::string& payload,
const securemessage::Header& header);
base::WeakPtrFactory<DeviceToDeviceInitiatorHelper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceToDeviceInitiatorHelper);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_DEVICE_TO_DEVICE_INITIATOR_HELPER_H_