blob: c8e0b3d24c519db332acc004d64c098caba28bd8 [file] [edit]
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "claim/manifest_store_view.h"
#include <string>
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "constants/labels.h"
#include "cose/sig_structure.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "jumbf/box.h"
#include "jumbf/test_utils.h"
#include "testing/jumbf_utils.h"
#include "uuid/uuid.h"
namespace credentio {
namespace {
using ::absl_testing::IsOk;
using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::testing::HasSubstr;
TEST(ManifestStoreViewTest, WrongManifestStoreUuid) {
std::string manifest_store = jumbf::EncodeSuperBox(
kClaimUuid, kManifestStoreLabel, {jumbf::EncodeCborBox("")});
EXPECT_THAT(ManifestStoreView::Create(manifest_store),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("No C2PA manifest store")));
}
TEST(ManifestStoreViewTest, WrongManifestStoreLabel) {
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, "wrong_label", {jumbf::EncodeCborBox("")});
EXPECT_THAT(ManifestStoreView::Create(manifest_store),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("No C2PA manifest store")));
}
TEST(ManifestStoreViewTest, SingleStandardManifest) {
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest1", {jumbf::EncodeCborBox("")});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
EXPECT_EQ(manifest_view->label(), "manifest1");
}
TEST(ManifestStoreViewTest, MultipleManifests) {
std::string manifest1 = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest1", {jumbf::EncodeCborBox("")});
std::string manifest2 = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest2", {jumbf::EncodeCborBox("")});
std::string manifest3 = jumbf::EncodeSuperBox(
kUpdateManifestUuid, "manifest3", {jumbf::EncodeCborBox("")});
std::string manifest_store =
jumbf::EncodeSuperBox(kManifestStoreUuid, kManifestStoreLabel,
{manifest1, manifest2, manifest3});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
EXPECT_EQ(manifest_view->label(), "manifest3");
}
TEST(ManifestStoreViewTest, NonManifestBoxesIgnored) {
std::string manifest1 = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest1", {jumbf::EncodeCborBox("")});
std::string manifest2 = jumbf::EncodeSuperBox(
kUpdateManifestUuid, "manifest2", {jumbf::EncodeCborBox("")});
std::string other_box1 =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box1",
{jumbf::EncodeCborBox("")});
std::string other_box2 =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box2",
{jumbf::EncodeCborBox("")});
std::string manifest_store =
jumbf::EncodeSuperBox(kManifestStoreUuid, kManifestStoreLabel,
{manifest1, other_box1, manifest2, other_box2});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
EXPECT_EQ(manifest_view->label(), "manifest2");
}
TEST(ManifestStoreViewTest, NoManifests) {
std::string other_box1 =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box1",
{jumbf::EncodeCborBox("")});
std::string other_box2 =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box2",
{jumbf::EncodeCborBox("")});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {other_box1, other_box2});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
EXPECT_THAT(view->GetActiveManifest(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("No active manifest found")));
}
TEST(ManifestStoreViewTest, CompressedManifestNotSupported) {
std::string standard_manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "label1", {jumbf::EncodeCborBox("")});
std::string compressed_manifest = jumbf::EncodeSuperBox(
kCompressedManifestUuid, "label2", {jumbf::EncodeCborBox("")});
std::string manifest_store =
jumbf::EncodeSuperBox(kManifestStoreUuid, kManifestStoreLabel,
{standard_manifest, compressed_manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
EXPECT_THAT(view->GetActiveManifest(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Compressed manifests are not supported")));
}
TEST(ManifestViewTest, NotManifest) {
std::string encoded_box =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box1",
{jumbf::EncodeCborBox("")});
jumbf::SuperBox box = ParseSuperBoxOrDie(&encoded_box);
EXPECT_THAT(ManifestView::Create(box),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Not a manifest box")));
}
TEST(ManifestViewTest, WrongClaimSignatureUuid) {
std::string claim_signature = jumbf::EncodeSuperBox(
kClaimUuid, kClaimSignatureLabel, {jumbf::EncodeCborBox("")});
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest_label", {claim_signature});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
auto result = manifest_view->GetClaimSignature();
EXPECT_THAT(result.status(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("No claim signature found in the manifest")));
}
TEST(ManifestViewTest, WrongClaimSignatureLabel) {
std::string claim_signature = jumbf::EncodeSuperBox(
kClaimSignatureUuid, "wrong_label", {jumbf::EncodeCborBox("")});
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest_label", {claim_signature});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
auto result = manifest_view->GetClaimSignature();
EXPECT_THAT(result.status(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("No claim signature found in the manifest")));
}
TEST(ClaimSignatureViewTest, NotClaimSignature) {
std::string encoded_box =
jumbf::EncodeSuperBox(UuidGenerator::Default().Generate(), "other_box1",
{jumbf::EncodeCborBox("")});
jumbf::SuperBox box = ParseSuperBoxOrDie(&encoded_box);
EXPECT_THAT(ClaimSignatureView::Create(box),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Not a claim signature box")));
}
TEST(ClaimSignatureViewTest, InvalidMultipleClaimSignature) {
std::string claim_signature = jumbf::EncodeSuperBox(
kClaimSignatureUuid, kClaimSignatureLabel,
{jumbf::EncodeCborBox("abc"), jumbf::EncodeCborBox("def")});
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest_label", {claim_signature});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
auto claim_signature_view = manifest_view->GetClaimSignature();
ASSERT_THAT(claim_signature_view, IsOk());
EXPECT_THAT(claim_signature_view->GetPayload(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Invalid claim signature box")));
}
TEST(ClaimSignatureViewTest, GetPayloadSuccess) {
std::string claim_signature = jumbf::EncodeSuperBox(
kClaimSignatureUuid, kClaimSignatureLabel, {jumbf::EncodeCborBox("abc")});
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest_label", {claim_signature});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
auto claim_signature_view = manifest_view->GetClaimSignature();
ASSERT_THAT(claim_signature_view, IsOk());
EXPECT_THAT(claim_signature_view->GetPayload(), IsOkAndHolds("abc"));
}
TEST(ClaimSignatureViewTest, GetStructSuccess) {
CoseSign1TaggedStructure cose_sign1{
.unprotected_header = {.sig_tst2 =
TstContainer{
.tst_tokens = {{.val = "timestamp"}}}},
.signature = "abc",
};
std::string claim_signature = jumbf::EncodeSuperBox(
kClaimSignatureUuid, kClaimSignatureLabel,
{jumbf::EncodeCborBox(EncodeCoseSign1TaggedStructure(cose_sign1))});
std::string manifest = jumbf::EncodeSuperBox(
kStandardManifestUuid, "manifest_label", {claim_signature});
std::string manifest_store = jumbf::EncodeSuperBox(
kManifestStoreUuid, kManifestStoreLabel, {manifest});
auto view = ManifestStoreView::Create(manifest_store);
ASSERT_THAT(view, IsOk());
auto manifest_view = view->GetActiveManifest();
ASSERT_THAT(manifest_view, IsOk());
auto claim_signature_view = manifest_view->GetClaimSignature();
ASSERT_THAT(claim_signature_view, IsOk());
EXPECT_THAT(claim_signature_view->GetStruct(), IsOkAndHolds(cose_sign1));
}
} // namespace
} // namespace credentio