| // 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 |