blob: a0189c3d53c807bdc84418975d41260a800b210f [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.
//
#ifndef THIRD_PARTY_CREDENTIO_VALIDATOR_GRAPH_H_
#define THIRD_PARTY_CREDENTIO_VALIDATOR_GRAPH_H_
#include <memory>
#include <optional>
#include <stack>
#include <string>
#include <vector>
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/die_if_null.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "assertion/validator.h"
#include "claim/validator.h"
#include "crypto/hash.h"
#include "jumbf/box.h"
#include "jumbf/uri.h"
#include "proto/assertion.pb.h"
#include "proto/manifest.pb.h"
#include "proto/validation_result.pb.h"
#include "proto/validation_status.pb.h"
#include "validator/tracker.h"
#include "validator/validator_options.h"
namespace credentio {
class ManifestGraph {
public:
ManifestGraph(const jumbf::SuperBox* absl_nonnull active_manifest,
const jumbf::UriResolver* absl_nonnull uri_resolver,
const AssertionValidator* absl_nonnull assertion_validator,
const ClaimValidator* absl_nonnull claim_validator,
const HashCheckerFactory* absl_nonnull hash_checker_factory,
const ValidatorOptions* absl_nonnull options)
: active_manifest_(*ABSL_DIE_IF_NULL(active_manifest)),
uri_resolver_(*ABSL_DIE_IF_NULL(uri_resolver)),
assertion_validator_(*ABSL_DIE_IF_NULL(assertion_validator)),
claim_validator_(*ABSL_DIE_IF_NULL(claim_validator)),
hash_checker_factory_(*ABSL_DIE_IF_NULL(hash_checker_factory)),
options_(*ABSL_DIE_IF_NULL(options)) {}
// Perform claim and assertion validation for the active manifest and all
// ingredient manifests reachable from the active manifest. Caller should
// follow with calling the `Validate` method from
// of bindings/validator.h to validate
// content bindings.
absl::StatusOr<std::unique_ptr<PartialValidationResultProto>> Validate();
private:
// Internal validation state of a manifest, tracking whether the manifest has
// been processed by `ValidateInternal` yet.
enum class InternalValidationState {
// `ValidateInternal` has not processed the manifest yet.
kUnvalidated,
// `ValidateInternal` is currently processing the manifest.
kBeingValidated,
// `ValidateInternal` has processed the manifest already.
kValidated,
};
struct IngredientAssertion {
const Assertion* assertion = nullptr;
std::string assertion_uri;
};
// State associated with a specific manifest during validation.
struct ManifestState {
InternalValidationState validation_state =
InternalValidationState::kUnvalidated;
// Absolute paths of all assertions in this manifest that have been reported
// (in another manifest) as redacted.
absl::flat_hash_set<std::string> redacted_assertions;
// Ingredient assertions that reference this manifest.
std::vector<IngredientAssertion> referencing_ingredient_assertions;
// Validation result, complete if `validation_state` is kValidated.
Manifest manifest;
};
// Returns the manifest state for the given path, creating it if it does not
// exist.
ManifestState& GetOrCreateManifestState(absl::string_view path);
// Returns the manifest state for the given path, or an error if the manifest
// is not yet validated.
absl::StatusOr<ManifestState* absl_nonnull> GetValidatedManifestState(
absl::string_view path);
// Performs the first pass of the ingredient validation algorithm in
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_performing_explicit_validation
// for the active manifest to populate the set of redacted assertions and the
// set of ingredient manifests and to perform claim and (non-redacted)
// assertion validation for all manifests in the graph.
absl::Status ValidateGraph();
absl::Status ValidateNode(const jumbf::SuperBox& node,
bool is_active_manifest,
std::stack<const jumbf::SuperBox*>& to_visit);
// This method performs the second pass of the ingredient validation algorithm
// in
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_performing_explicit_validation.
// In this pass, we perform the hash validation checks for all ingredient
// manifests reachable from the active manifest, using claim signature or
// manifest hash validation methods. We also process the `validationResults`
// sections of v3 ingredient assertions and update the
// `PartialValidationResultProto` accordingly.
absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ValidateWithRedactions(std::unique_ptr<PartialValidationResultProto> result);
// Records the given redaction in the `redacted_assertions_` map.
void ProcessRedaction(absl::string_view redacted_assertion_uri,
absl::string_view manifest_path,
ValidationTracker& tracker);
// Processes the given ingredient assertion, returning the absolute path to
// the ingredient's manifest if it should be processed.
std::optional<std::string> ProcessIngredientAssertion(
const Assertion& assertion, absl::string_view manifest_path,
absl::string_view default_algorithm, ValidationTracker& tracker);
// Performs post-processing to complete population of the validation result
// following graph traversal via ValidateNode.
absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ValidatePostProcess();
// RAII-style lock to manage validation state transitions using local scope.
class InternalValidationStateLock {
public:
explicit InternalValidationStateLock(
ManifestState* absl_nonnull manifest_state);
~InternalValidationStateLock();
private:
ManifestState& manifest_state_;
};
const jumbf::SuperBox& active_manifest_;
const jumbf::UriResolver& uri_resolver_;
const AssertionValidator& assertion_validator_;
const ClaimValidator& claim_validator_;
const HashCheckerFactory& hash_checker_factory_;
const ValidatorOptions& options_;
// Manifest validation states, keyed by manifest path.
absl::flat_hash_map<std::string, std::unique_ptr<ManifestState>> manifests_;
// Ingredient manifest paths, in pre-order traversal ordering.
std::vector<std::string> ingredient_manifest_paths_;
std::string manifest_with_content_bindings_label_;
};
} // namespace credentio
#endif // THIRD_PARTY_CREDENTIO_VALIDATOR_GRAPH_H_