| // 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::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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| auto claim_signature_view = manifest_view->GetClaimSignature(); | |
| ABSL_ASSERT_OK(claim_signature_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| auto claim_signature_view = manifest_view->GetClaimSignature(); | |
| ABSL_ASSERT_OK(claim_signature_view); | |
| 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); | |
| ABSL_ASSERT_OK(view); | |
| auto manifest_view = view->GetActiveManifest(); | |
| ABSL_ASSERT_OK(manifest_view); | |
| auto claim_signature_view = manifest_view->GetClaimSignature(); | |
| ABSL_ASSERT_OK(claim_signature_view); | |
| EXPECT_THAT(claim_signature_view->GetStruct(), IsOkAndHolds(cose_sign1)); | |
| } | |
| } // namespace | |
| } // namespace credentio |