summaryrefslogtreecommitdiffstats
path: root/components/proximity_auth
diff options
context:
space:
mode:
authortengs <tengs@chromium.org>2015-07-20 17:20:35 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-21 00:21:17 +0000
commit7b425ad85c9afdd4195794cc51ee0316bbcc0464 (patch)
treeb06e8e98e9982ad2ac912875428cedb283f84639 /components/proximity_auth
parentb6a6f9f0c840623c7b0cd9b9e413b6b22afdf71b (diff)
downloadchromium_src-7b425ad85c9afdd4195794cc51ee0316bbcc0464.zip
chromium_src-7b425ad85c9afdd4195794cc51ee0316bbcc0464.tar.gz
chromium_src-7b425ad85c9afdd4195794cc51ee0316bbcc0464.tar.bz2
Implement proximity_auth::WireMessage::Serialize().
This function returns a serialized byte representation of a WireMessage that is sent to the Phone in the Smart Lock protocol. This CL also fixes a bug when parsing the body size from the header. Bytes not fitting into a signed char are not parsed properly. BUG=508761 TEST=unit test Review URL: https://codereview.chromium.org/1240633003 Cr-Commit-Position: refs/heads/master@{#339572}
Diffstat (limited to 'components/proximity_auth')
-rw-r--r--components/proximity_auth/wire_message.cc71
-rw-r--r--components/proximity_auth/wire_message_unittest.cc57
2 files changed, 112 insertions, 16 deletions
diff --git a/components/proximity_auth/wire_message.cc b/components/proximity_auth/wire_message.cc
index 0501359..7906615 100644
--- a/components/proximity_auth/wire_message.cc
+++ b/components/proximity_auth/wire_message.cc
@@ -4,11 +4,14 @@
#include "components/proximity_auth/wire_message.h"
+#include <limits>
+
#include "base/json/json_reader.h"
-#include "base/logging.h"
+#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/values.h"
#include "components/proximity_auth/cryptauth/base64url.h"
+#include "components/proximity_auth/logging/logging.h"
// The wire messages have a simple format:
// [ message version ] [ body length ] [ JSON body ]
@@ -23,7 +26,7 @@ namespace {
const size_t kHeaderLength = 3;
// The protocol version of the message format.
-const int kExpectedMessageFormatVersion = 3;
+const int kMessageFormatVersionThree = 3;
const char kPayloadKey[] = "payload";
const char kPermitIdKey[] = "permit_id";
@@ -43,24 +46,24 @@ bool ParseHeader(const std::string& serialized_message,
static_assert(kHeaderLength > 2, "kHeaderLength too small");
size_t version = serialized_message[0];
- if (version != kExpectedMessageFormatVersion) {
- VLOG(1) << "Error: Invalid message version. Got " << version
- << ", expected " << kExpectedMessageFormatVersion;
+ if (version != kMessageFormatVersionThree) {
+ PA_LOG(WARNING) << "Error: Invalid message version. Got " << version
+ << ", expected " << kMessageFormatVersionThree;
return false;
}
- size_t expected_body_length =
- (static_cast<size_t>(serialized_message[1]) << 8) |
- (static_cast<size_t>(serialized_message[2]) << 0);
+ uint16_t expected_body_length =
+ (static_cast<uint8_t>(serialized_message[1]) << 8) |
+ (static_cast<uint8_t>(serialized_message[2]) << 0);
size_t expected_message_length = kHeaderLength + expected_body_length;
if (serialized_message.size() < expected_message_length) {
*is_incomplete_message = true;
return false;
}
if (serialized_message.size() != expected_message_length) {
- VLOG(1) << "Error: Invalid message length. Got "
- << serialized_message.size() << ", expected "
- << expected_message_length;
+ PA_LOG(WARNING) << "Error: Invalid message length. Got "
+ << serialized_message.size() << ", expected "
+ << expected_message_length;
return false;
}
@@ -82,7 +85,7 @@ scoped_ptr<WireMessage> WireMessage::Deserialize(
scoped_ptr<base::Value> body_value(base::JSONReader::DeprecatedRead(
serialized_message.substr(kHeaderLength)));
if (!body_value || !body_value->IsType(base::Value::TYPE_DICTIONARY)) {
- VLOG(1) << "Error: Unable to parse message as JSON.";
+ PA_LOG(WARNING) << "Error: Unable to parse message as JSON.";
return scoped_ptr<WireMessage>();
}
@@ -98,13 +101,13 @@ scoped_ptr<WireMessage> WireMessage::Deserialize(
std::string payload_base64;
if (!body->GetString(kPayloadKey, &payload_base64) ||
payload_base64.empty()) {
- VLOG(1) << "Error: Missing payload.";
+ PA_LOG(WARNING) << "Error: Missing payload.";
return scoped_ptr<WireMessage>();
}
std::string payload;
if (!Base64UrlDecode(payload_base64, &payload)) {
- VLOG(1) << "Error: Invalid base64 encoding for payload.";
+ PA_LOG(WARNING) << "Error: Invalid base64 encoding for payload.";
return scoped_ptr<WireMessage>();
}
@@ -112,8 +115,44 @@ scoped_ptr<WireMessage> WireMessage::Deserialize(
}
std::string WireMessage::Serialize() const {
- // TODO(isherman): Implement.
- return "This method is not yet implemented.";
+ if (payload_.empty()) {
+ PA_LOG(ERROR) << "Failed to serialize empty wire message.";
+ return std::string();
+ }
+
+ // Create JSON body containing permit id and payload.
+ base::DictionaryValue body;
+ if (!permit_id_.empty())
+ body.SetString(kPermitIdKey, permit_id_);
+
+ std::string base64_payload;
+ Base64UrlEncode(payload_, &base64_payload);
+ body.SetString(kPayloadKey, base64_payload);
+
+ std::string json_body;
+ if (!base::JSONWriter::Write(body, &json_body)) {
+ PA_LOG(ERROR) << "Failed to convert WireMessage body to JSON: " << body;
+ return std::string();
+ }
+
+ // Create header containing version and payload size.
+ size_t body_size = json_body.size();
+ if (body_size > std::numeric_limits<uint16_t>::max()) {
+ PA_LOG(ERROR) << "Can not create WireMessage because body size exceeds "
+ << "16-bit unsigned integer: " << body_size;
+ return std::string();
+ }
+
+ uint8_t header[] = {
+ static_cast<uint8_t>(kMessageFormatVersionThree),
+ static_cast<uint8_t>((body_size >> 8) & 0xFF),
+ static_cast<uint8_t>(body_size & 0xFF),
+ };
+ static_assert(sizeof(header) == kHeaderLength, "Malformed header.");
+
+ std::string header_string(kHeaderLength, 0);
+ std::memcpy(&header_string[0], header, kHeaderLength);
+ return header_string + json_body;
}
WireMessage::WireMessage(const std::string& permit_id,
diff --git a/components/proximity_auth/wire_message_unittest.cc b/components/proximity_auth/wire_message_unittest.cc
index 68ce086..4411ff8 100644
--- a/components/proximity_auth/wire_message_unittest.cc
+++ b/components/proximity_auth/wire_message_unittest.cc
@@ -4,6 +4,7 @@
#include "components/proximity_auth/wire_message.h"
+#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace proximity_auth {
@@ -176,4 +177,60 @@ TEST(ProximityAuthWireMessage, Deserialize_ValidMessageWithExtraUnknownFields) {
EXPECT_EQ("a", message->payload());
}
+TEST(ProximityAuthWireMessage, Deserialize_SizeEquals0x01FF) {
+ // Create a message with a body of 0x01FF bytes to test the size contained in
+ // the header is parsed correctly.
+ std::string header("\3\x01\xff", 3);
+ char json_template[] = "{\"payload\":\"YQ==\", \"filler\":\"$1\"}";
+ // Add 3 to the size to take into account the "$1" and NUL terminator ("\0")
+ // characters in |json_template|.
+ uint16_t filler_size = 0x01ff - sizeof(json_template) + 3;
+ std::string filler(filler_size, 'F');
+
+ std::string body = base::ReplaceStringPlaceholders(
+ json_template, std::vector<std::string>(1u, filler), nullptr);
+ std::string serialized_message = header + body;
+
+ bool is_incomplete;
+ scoped_ptr<WireMessage> message =
+ WireMessage::Deserialize(serialized_message, &is_incomplete);
+ EXPECT_FALSE(is_incomplete);
+ ASSERT_TRUE(message);
+ EXPECT_EQ("a", message->payload());
+}
+
+TEST(ProximityAuthWireMessage, Serialize_WithPermitId) {
+ WireMessage message1("example id", "example payload");
+ std::string bytes = message1.Serialize();
+ ASSERT_FALSE(bytes.empty());
+
+ bool is_incomplete;
+ scoped_ptr<WireMessage> message2 =
+ WireMessage::Deserialize(bytes, &is_incomplete);
+ EXPECT_FALSE(is_incomplete);
+ ASSERT_TRUE(message2);
+ EXPECT_EQ("example id", message2->permit_id());
+ EXPECT_EQ("example payload", message2->payload());
+}
+
+TEST(ProximityAuthWireMessage, Serialize_WithoutPermitId) {
+ WireMessage message1(std::string(), "example payload");
+ std::string bytes = message1.Serialize();
+ ASSERT_FALSE(bytes.empty());
+
+ bool is_incomplete;
+ scoped_ptr<WireMessage> message2 =
+ WireMessage::Deserialize(bytes, &is_incomplete);
+ EXPECT_FALSE(is_incomplete);
+ ASSERT_TRUE(message2);
+ EXPECT_EQ(std::string(), message2->permit_id());
+ EXPECT_EQ("example payload", message2->payload());
+}
+
+TEST(ProximityAuthWireMessage, Serialize_FailsWithoutPayload) {
+ WireMessage message1("example id", std::string());
+ std::string bytes = message1.Serialize();
+ EXPECT_TRUE(bytes.empty());
+}
+
} // namespace proximity_auth