blob: 54bd35052af5ca422178c8c16038c4c8a0e6c61f [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/legion/session_deserializer.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/values.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/oak/chromium/proto/session/session.pb.h"
#include "third_party/oak/chromium/proto/session/session.test.h"
#include "third_party/oak/chromium/proto/session/session.to_value.h"
namespace legion {
namespace {
using ::testing::IsEmpty;
using ::testing::SizeIs;
TEST(SessionDeserializerTest, DeserializeHandshakeResponseSuccess) {
const char kValidJson[] = R"(
{
"handshake_response": {
"noise_handshake_message": {
"ephemeral_public_key": "ZV9rZXk=",
"static_public_key": "c19rZXk=",
"ciphertext": "c2VjcmV0"
},
"attestation_bindings": {
"key1": {
"binding": "YmluZGluZzE="
}
},
"assertion_bindings": {
"key2": {
"binding": "YmluZGluZzI="
}
}
}
}
)";
std::optional<base::Value> value =
base::JSONReader::Read(kValidJson, base::JSON_PARSE_RFC);
ASSERT_TRUE(value.has_value());
oak::session::v1::SessionResponse session_response;
EXPECT_TRUE(DeserializeSessionResponse(*value, &session_response));
EXPECT_TRUE(session_response.has_handshake_response());
auto response = session_response.handshake_response();
EXPECT_EQ(response.noise_handshake_message().ephemeral_public_key(), "e_key");
EXPECT_EQ(response.noise_handshake_message().static_public_key(), "s_key");
EXPECT_EQ(response.noise_handshake_message().ciphertext(), "secret");
ASSERT_THAT(response.attestation_bindings(), SizeIs(1));
EXPECT_EQ(response.attestation_bindings().at("key1").binding(), "binding1");
ASSERT_THAT(response.assertion_bindings(), SizeIs(1));
EXPECT_EQ(response.assertion_bindings().at("key2").binding(), "binding2");
}
TEST(SessionDeserializerTest, DeserializeHandshakeResponseEmptyMaps) {
const char kJson[] = R"({
"handshake_response": {
"noise_handshake_message": {
"ephemeral_public_key": "ZV9rZXk="
}
}
})";
std::optional<base::Value> value =
base::JSONReader::Read(kJson, base::JSON_PARSE_RFC);
ASSERT_TRUE(value.has_value());
oak::session::v1::SessionResponse session_response;
EXPECT_TRUE(DeserializeSessionResponse(*value, &session_response));
EXPECT_TRUE(session_response.has_handshake_response());
auto response = session_response.handshake_response();
EXPECT_EQ(response.noise_handshake_message().ephemeral_public_key(), "e_key");
EXPECT_THAT(response.attestation_bindings(), IsEmpty());
EXPECT_THAT(response.assertion_bindings(), IsEmpty());
}
TEST(SessionDeserializerTest, DeserializeNotADictionary) {
base::Value value(base::Value::Type::LIST);
oak::session::v1::SessionResponse response;
EXPECT_FALSE(DeserializeSessionResponse(value, &response));
}
TEST(SessionDeserializerTest, DeserializeInvalidNestedType) {
const char kJson[] = R"({
"handshake_response": "not_a_dict"
})";
std::optional<base::Value> value =
base::JSONReader::Read(kJson, base::JSON_PARSE_RFC);
ASSERT_TRUE(value.has_value());
oak::session::v1::SessionResponse response;
EXPECT_FALSE(DeserializeSessionResponse(*value, &response));
}
TEST(SessionDeserializerTest, HandshakeResponseToJsonAndBack) {
oak::session::v1::SessionResponse session_proto;
auto* handshake_proto = session_proto.mutable_handshake_response();
handshake_proto->mutable_noise_handshake_message()->set_ephemeral_public_key(
"test_ephemeral_key");
handshake_proto->mutable_noise_handshake_message()->set_static_public_key(
"test_static_key");
handshake_proto->mutable_noise_handshake_message()->set_ciphertext(
"test_ciphertext");
base::Value value = oak::session::v1::Serialize(session_proto);
oak::session::v1::SessionResponse deserialized_proto;
ASSERT_TRUE(DeserializeSessionResponse(value, &deserialized_proto));
EXPECT_THAT(session_proto,
oak::session::v1::EqualsSessionResponse(deserialized_proto));
}
} // namespace
} // namespace legion