blob: 97bde31f60bf525dcc491c6c99e0386360c1baa6 [file]
// 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