| // 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 COMPONENTS_CRYPTAUTH_DEVICE_TO_DEVICE_INITIATOR_HELPER_H_ |
| #define COMPONENTS_CRYPTAUTH_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 "components/cryptauth/proto/securemessage.pb.h" |
| #include "components/cryptauth/session_keys.h" |
| |
| namespace cryptauth { |
| |
| class SecureMessageDelegate; |
| |
| // 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, |
| 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, |
| 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, |
| 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, |
| 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; |
| 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, |
| 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 cryptauth |
| |
| #endif // COMPONENTS_CRYPTAUTH_DEVICE_TO_DEVICE_INITIATOR_HELPER_H_ |