blob: 7e5a3df4c269a06f8b6cae704a76241cbdddf1d0 [file] [log] [blame]
// Copyright 2018 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.
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "base/strings/string_piece.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "content/public/common/content_paths.h"
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
cbor::Value CBORByteString(base::StringPiece str) {
return cbor::Value(str, cbor::Value::Type::BYTE_STRING);
}
} // namespace
TEST(SignedExchangeCertificateParseTest, Empty) {
auto parsed = SignedExchangeCertificateChain::Parse(
base::span<const uint8_t>(), nullptr);
EXPECT_FALSE(parsed);
}
TEST(SignedExchangeCertificateParseTest, EmptyChain) {
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
TEST(SignedExchangeCertificateParseTest, MissingCert) {
cbor::Value::MapValue cbor_map;
cbor_map[cbor::Value("sct")] = CBORByteString("SCT");
cbor_map[cbor::Value("ocsp")] = CBORByteString("OCSP");
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
cbor_array.push_back(cbor::Value(std::move(cbor_map)));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
TEST(SignedExchangeCertificateParseTest, OneCert) {
net::CertificateList certs;
ASSERT_TRUE(
net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
ASSERT_EQ(1U, certs.size());
base::StringPiece cert_der =
net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
cbor::Value::MapValue cbor_map;
cbor_map[cbor::Value("sct")] = CBORByteString("SCT");
cbor_map[cbor::Value("cert")] = CBORByteString(cert_der);
cbor_map[cbor::Value("ocsp")] = CBORByteString("OCSP");
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
cbor_array.push_back(cbor::Value(std::move(cbor_map)));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
ASSERT_TRUE(parsed);
EXPECT_EQ(cert_der, net::x509_util::CryptoBufferAsStringPiece(
parsed->cert()->cert_buffer()));
ASSERT_EQ(0U, parsed->cert()->intermediate_buffers().size());
EXPECT_EQ(parsed->ocsp(), base::make_optional<std::string>("OCSP"));
EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
}
TEST(SignedExchangeCertificateParseTest, MissingOCSPInFirstCert) {
net::CertificateList certs;
ASSERT_TRUE(
net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
ASSERT_EQ(1U, certs.size());
base::StringPiece cert_der =
net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
cbor::Value::MapValue cbor_map;
cbor_map[cbor::Value("sct")] = CBORByteString("SCT");
cbor_map[cbor::Value("cert")] = CBORByteString(cert_der);
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
cbor_array.push_back(cbor::Value(std::move(cbor_map)));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
TEST(SignedExchangeCertificateParseTest, TwoCerts) {
net::CertificateList certs;
ASSERT_TRUE(net::LoadCertificateFiles(
{"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
ASSERT_EQ(2U, certs.size());
base::StringPiece cert1_der =
net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
base::StringPiece cert2_der =
net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
cbor::Value::MapValue cbor_map1;
cbor_map1[cbor::Value("sct")] = CBORByteString("SCT");
cbor_map1[cbor::Value("cert")] = CBORByteString(cert1_der);
cbor_map1[cbor::Value("ocsp")] = CBORByteString("OCSP");
cbor::Value::MapValue cbor_map2;
cbor_map2[cbor::Value("cert")] = CBORByteString(cert2_der);
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
cbor_array.push_back(cbor::Value(std::move(cbor_map1)));
cbor_array.push_back(cbor::Value(std::move(cbor_map2)));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
ASSERT_TRUE(parsed);
EXPECT_EQ(cert1_der, net::x509_util::CryptoBufferAsStringPiece(
parsed->cert()->cert_buffer()));
ASSERT_EQ(1U, parsed->cert()->intermediate_buffers().size());
EXPECT_EQ(cert2_der, net::x509_util::CryptoBufferAsStringPiece(
parsed->cert()->intermediate_buffers()[0].get()));
EXPECT_EQ(parsed->ocsp(), base::make_optional<std::string>("OCSP"));
EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
}
TEST(SignedExchangeCertificateParseTest, HavingOCSPInSecondCert) {
net::CertificateList certs;
ASSERT_TRUE(net::LoadCertificateFiles(
{"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
ASSERT_EQ(2U, certs.size());
base::StringPiece cert1_der =
net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
base::StringPiece cert2_der =
net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
cbor::Value::MapValue cbor_map1;
cbor_map1[cbor::Value("sct")] = CBORByteString("SCT");
cbor_map1[cbor::Value("cert")] = CBORByteString(cert1_der);
cbor_map1[cbor::Value("ocsp")] = CBORByteString("OCSP1");
cbor::Value::MapValue cbor_map2;
cbor_map2[cbor::Value("cert")] = CBORByteString(cert2_der);
cbor_map2[cbor::Value("ocsp")] = CBORByteString("OCSP2");
cbor::Value::ArrayValue cbor_array;
cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
cbor_array.push_back(cbor::Value(std::move(cbor_map1)));
cbor_array.push_back(cbor::Value(std::move(cbor_map2)));
auto serialized = cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
ASSERT_TRUE(serialized.has_value());
auto parsed = SignedExchangeCertificateChain::Parse(
base::make_span(*serialized), nullptr);
EXPECT_FALSE(parsed);
}
TEST(SignedExchangeCertificateParseTest, ParseGoldenFile) {
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
path =
path.AppendASCII("sxg").AppendASCII("test.example.org.public.pem.cbor");
std::string contents;
ASSERT_TRUE(base::ReadFileToString(path, &contents));
auto parsed = SignedExchangeCertificateChain::Parse(
base::as_bytes(base::make_span(contents)), nullptr);
ASSERT_TRUE(parsed);
}
} // namespace content