1 // Copyright 2015 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.
5 #include "components/proximity_auth/device_to_device_secure_context.h"
8 #include "base/callback.h"
9 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
10 #include "components/proximity_auth/cryptauth/proto/securemessage.pb.h"
11 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
12 #include "components/proximity_auth/logging/logging.h"
14 namespace proximity_auth
{
18 // The version to put in the GcmMetadata field.
19 const int kGcmMetadataVersion
= 1;
21 // The sequence number of the last message used during authentication. These
22 // messages are sent and received before the SecureContext is created.
23 const int kAuthenticationSequenceNumber
= 2;
27 DeviceToDeviceSecureContext::DeviceToDeviceSecureContext(
28 scoped_ptr
<SecureMessageDelegate
> secure_message_delegate
,
29 const std::string
& symmetric_key
,
30 const std::string
& responder_auth_message
,
31 ProtocolVersion protocol_version
)
32 : secure_message_delegate_(secure_message_delegate
.Pass()),
33 symmetric_key_(symmetric_key
),
34 responder_auth_message_(responder_auth_message
),
35 protocol_version_(protocol_version
),
36 last_sequence_number_(kAuthenticationSequenceNumber
),
37 weak_ptr_factory_(this) {}
39 DeviceToDeviceSecureContext::~DeviceToDeviceSecureContext() {}
41 void DeviceToDeviceSecureContext::Decode(const std::string
& encoded_message
,
42 const MessageCallback
& callback
) {
43 SecureMessageDelegate::UnwrapOptions unwrap_options
;
44 unwrap_options
.encryption_scheme
= securemessage::AES_256_CBC
;
45 unwrap_options
.signature_scheme
= securemessage::HMAC_SHA256
;
47 secure_message_delegate_
->UnwrapSecureMessage(
48 encoded_message
, symmetric_key_
, unwrap_options
,
49 base::Bind(&DeviceToDeviceSecureContext::HandleUnwrapResult
,
50 weak_ptr_factory_
.GetWeakPtr(), callback
));
53 void DeviceToDeviceSecureContext::Encode(const std::string
& message
,
54 const MessageCallback
& callback
) {
55 // Create a GcmMetadata field to put in the header.
56 cryptauth::GcmMetadata gcm_metadata
;
57 gcm_metadata
.set_type(cryptauth::DEVICE_TO_DEVICE_MESSAGE
);
58 gcm_metadata
.set_version(kGcmMetadataVersion
);
60 // Wrap |message| inside a DeviceToDeviceMessage proto.
61 securemessage::DeviceToDeviceMessage device_to_device_message
;
62 device_to_device_message
.set_sequence_number(++last_sequence_number_
);
63 device_to_device_message
.set_message(message
);
65 SecureMessageDelegate::CreateOptions create_options
;
66 create_options
.encryption_scheme
= securemessage::AES_256_CBC
;
67 create_options
.signature_scheme
= securemessage::HMAC_SHA256
;
68 gcm_metadata
.SerializeToString(&create_options
.public_metadata
);
70 secure_message_delegate_
->CreateSecureMessage(
71 device_to_device_message
.SerializeAsString(), symmetric_key_
,
72 create_options
, callback
);
75 std::string
DeviceToDeviceSecureContext::GetReceivedAuthMessage() const {
76 return responder_auth_message_
;
79 SecureContext::ProtocolVersion
DeviceToDeviceSecureContext::GetProtocolVersion()
81 return protocol_version_
;
84 void DeviceToDeviceSecureContext::HandleUnwrapResult(
85 const DeviceToDeviceSecureContext::MessageCallback
& callback
,
87 const std::string
& payload
,
88 const securemessage::Header
& header
) {
89 // The payload should contain a DeviceToDeviceMessage proto.
90 securemessage::DeviceToDeviceMessage device_to_device_message
;
91 if (!verified
|| !device_to_device_message
.ParseFromString(payload
)) {
92 PA_LOG(ERROR
) << "Failed to unwrap secure message.";
93 callback
.Run(std::string());
97 // Check that the sequence number matches the expected sequence number.
98 if (device_to_device_message
.sequence_number() != last_sequence_number_
+ 1) {
99 PA_LOG(ERROR
) << "Expected sequence_number=" << last_sequence_number_
+ 1
100 << ", but got " << device_to_device_message
.sequence_number();
101 callback
.Run(std::string());
105 // Validate the GcmMetadata proto in the header.
106 cryptauth::GcmMetadata gcm_metadata
;
107 if (!gcm_metadata
.ParseFromString(header
.public_metadata()) ||
108 gcm_metadata
.type() != cryptauth::DEVICE_TO_DEVICE_MESSAGE
||
109 gcm_metadata
.version() != kGcmMetadataVersion
) {
110 PA_LOG(ERROR
) << "Failed to validate GcmMetadata.";
111 callback
.Run(std::string());
115 last_sequence_number_
++;
116 callback
.Run(device_to_device_message
.message());