| // 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 <optional> |
| #include <utility> |
| |
| #include "absl/status/status.h" |
| #include "absl/status/status_macros.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "constants/labels.h" |
| #include "cose/sig_structure.h" |
| #include "jumbf/box.h" |
| #include "jumbf/parse.h" |
| |
| namespace credentio { |
| namespace { |
| bool IsManifestStore(const jumbf::SuperBox& superbox) { |
| return superbox.description.type_uuid == kManifestStoreUuid && |
| superbox.description.label == kManifestStoreLabel; |
| } |
| |
| bool IsManifest(const jumbf::SuperBox& superbox) { |
| return superbox.description.type_uuid == kStandardManifestUuid || |
| superbox.description.type_uuid == kUpdateManifestUuid || |
| superbox.description.type_uuid == kTimestampManifestUuid || |
| superbox.description.type_uuid == kCompressedManifestUuid; |
| } |
| |
| bool IsClaimSignature(const jumbf::SuperBox& superbox) { |
| return superbox.description.type_uuid == kClaimSignatureUuid && |
| superbox.description.label == kClaimSignatureLabel; |
| } |
| } // namespace |
| |
| absl::StatusOr<ManifestStoreView> ManifestStoreView::Create( |
| absl::string_view manifest_store) { |
| ABSL_ASSIGN_OR_RETURN( |
| auto super_box_res, |
| jumbf::ConsumeSuperBox(&manifest_store, /*recursion_limit=*/4)); |
| jumbf::SuperBox super_box = std::move(super_box_res); |
| if (!IsManifestStore(super_box)) { |
| return absl::InvalidArgumentError("No C2PA manifest store"); |
| } |
| return ManifestStoreView(std::move(super_box)); |
| } |
| |
| absl::StatusOr<ManifestView> ManifestStoreView::GetActiveManifest() const { |
| const jumbf::SuperBox* active_manifest = nullptr; |
| for (const auto& box : superbox_.contents) { |
| if (box.Holds<jumbf::SuperBox>()) { |
| const auto& superbox = box.Get<jumbf::SuperBox>(); |
| if (IsManifest(superbox)) { |
| active_manifest = &superbox; |
| } |
| } |
| } |
| if (active_manifest == nullptr) { |
| return absl::InvalidArgumentError("No active manifest found"); |
| } |
| return ManifestView::Create(*active_manifest); |
| } |
| |
| absl::StatusOr<ManifestView> ManifestView::Create(jumbf::SuperBox superbox) { |
| if (!IsManifest(superbox)) { |
| return absl::InvalidArgumentError("Not a manifest box"); |
| } |
| if (superbox.description.type_uuid == kCompressedManifestUuid) { |
| return absl::InvalidArgumentError("Compressed manifests are not supported"); |
| } |
| return ManifestView(std::move(superbox)); |
| } |
| |
| absl::StatusOr<ClaimSignatureView> ManifestView::GetClaimSignature() const { |
| std::optional<jumbf::SuperBox> claim_signature_superbox = std::nullopt; |
| for (const auto& content : superbox_.contents) { |
| if (content.Holds<jumbf::SuperBox>() && |
| IsClaimSignature(content.Get<jumbf::SuperBox>())) { |
| claim_signature_superbox = content.Get<jumbf::SuperBox>(); |
| break; |
| } |
| } |
| if (!claim_signature_superbox.has_value()) { |
| return absl::InvalidArgumentError( |
| "No claim signature found in the manifest"); |
| } |
| return ClaimSignatureView::Create(claim_signature_superbox.value()); |
| } |
| |
| absl::string_view ManifestView::label() const { |
| return superbox_.description.label.value_or(""); |
| } |
| |
| absl::StatusOr<ClaimSignatureView> ClaimSignatureView::Create( |
| jumbf::SuperBox superbox) { |
| if (!IsClaimSignature(superbox)) { |
| return absl::InvalidArgumentError("Not a claim signature box"); |
| } |
| return ClaimSignatureView(std::move(superbox)); |
| } |
| |
| absl::StatusOr<absl::string_view> ClaimSignatureView::GetPayload() const { |
| if (superbox_.contents.size() != 1 || |
| !superbox_.contents[0].Holds<jumbf::CborBox>()) { |
| return absl::InvalidArgumentError("Invalid claim signature box"); |
| } |
| return superbox_.contents[0].Get<jumbf::CborBox>().payload; |
| } |
| |
| absl::StatusOr<CoseSign1TaggedStructure> ClaimSignatureView::GetStruct() const { |
| ABSL_ASSIGN_OR_RETURN(auto payload_res, GetPayload()); |
| return DecodeCoseSign1TaggedStructure(payload_res); |
| } |
| |
| } // namespace credentio |