blob: b30e6d68edef2f94d475d97e7d6fc36acd5611dc [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 "generator/generator_factory.h"
#include <memory>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "assertion/assertion_encoder.h"
#include "async/async_context.h"
#include "claim/claim_cbor_encoder.h"
#include "claim/generator.h"
#include "claim/manifest_box_assembler.h"
#include "claim/signer.h"
#include "crypto/hash.h"
#include "generator/generator.h"
#include "generator/generator_impl.h"
#include "generator/generator_options.h"
namespace credentio {
namespace {
// A ManifestStoreGenerator implementation that routes generation requests
// between two underlying generators:
// - `signing_generator`: used for full manifest store generation and
// finalization with real signatures.
// - `template_generator`: used for manifest store template generation for size
// estimation.
// Also retains ownership of `template_hash_factory` to guarantee its lifetime.
class DualModeManifestStoreGenerator : public ManifestStoreGenerator {
public:
// Constructs a DualModeManifestStoreGenerator with the given signing and
// template generators, optionally retaining ownership of
// `template_hash_factory`.
DualModeManifestStoreGenerator(
std::unique_ptr<ManifestStoreGenerator> absl_nonnull signing_generator,
std::unique_ptr<ManifestStoreGenerator> absl_nonnull template_generator,
std::unique_ptr<HasherFactory> absl_nullable template_hash_factory =
nullptr)
: signing_generator_(std::move(signing_generator)),
template_hash_factory_(std::move(template_hash_factory)),
template_generator_(std::move(template_generator)) {}
// Generates a manifest store using the signing generator.
void GenerateManifestStore(
GenerateManifestStoreRequest request, AsyncContext context,
absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
cb) const override {
signing_generator_->GenerateManifestStore(
std::move(request), std::move(context), std::move(cb));
}
// Generates a manifest store template for size estimation using the template
// generator.
void GenerateManifestStoreTemplate(
GenerateManifestStoreRequest request, AsyncContext context,
absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
const override {
template_generator_->GenerateManifestStoreTemplate(
std::move(request), std::move(context), std::move(cb));
}
// Finalizes the manifest store using the signing generator.
void FinalizeManifestStore(
FinalizeManifestStoreRequest request, AsyncContext context,
absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
cb) const override {
signing_generator_->FinalizeManifestStore(
std::move(request), std::move(context), std::move(cb));
}
private:
std::unique_ptr<ManifestStoreGenerator> signing_generator_;
// Must be declared before `template_generator_` so it outlives
// `template_generator_`.
std::unique_ptr<HasherFactory> template_hash_factory_;
std::unique_ptr<ManifestStoreGenerator> template_generator_;
};
// Helper function to create an underlying ManifestStoreGeneratorImpl with the
// given options, hash factory, and claim signer.
absl::StatusOr<std::unique_ptr<ManifestStoreGenerator>> CreateGenerator(
const GeneratorOptions& options,
const HasherFactory* absl_nonnull hash_factory,
ClaimSigner* absl_nonnull claim_signer) {
ABSL_ASSIGN_OR_RETURN(auto manifest_assembler,
options.manifest_assembler_factory({
.uuid_generator = options.uuid_generator,
.hash_factory = hash_factory,
.spec_version = options.spec_version,
}));
ABSL_ASSIGN_OR_RETURN(
auto manifest_encoder,
CreateManifestEncoder({
.generator_info = options.generator_info,
.claim_signer = claim_signer,
.assertion_cbor_encoder = options.assertion_cbor_encoder
? options.assertion_cbor_encoder
: &GetAssertionEncoder(),
.claim_cbor_encoder = options.claim_cbor_encoder
? options.claim_cbor_encoder
: &GetClaimCborEncoder(),
.hash_factory = hash_factory,
}));
return std::make_unique<ManifestStoreGeneratorImpl>(
std::move(manifest_assembler), std::move(manifest_encoder),
options.manifest_store_transformer);
}
// Validates that required options are provided.
absl::Status ValidateOptions(const GeneratorOptions& options) {
if (options.signing_claim_signer == nullptr) {
return absl::InvalidArgumentError("signing_claim_signer is required");
}
if (options.template_claim_signer == nullptr) {
return absl::InvalidArgumentError("template_claim_signer is required");
}
if (options.uuid_generator == nullptr) {
return absl::InvalidArgumentError("uuid_generator is required");
}
if (options.hash_factory == nullptr) {
return absl::InvalidArgumentError("hash_factory is required");
}
if (options.manifest_assembler_factory == nullptr) {
return absl::InvalidArgumentError("manifest_assembler_factory is required");
}
return absl::OkStatus();
}
} // namespace
absl::StatusOr<std::unique_ptr<ManifestStoreGenerator>> CreateGenerator(
GeneratorOptions options) {
ABSL_RETURN_IF_ERROR(ValidateOptions(options));
auto template_hash_factory = std::make_unique<TemplatedHasherFactory>(
options.hash_factory->algorithm());
ABSL_ASSIGN_OR_RETURN(auto signing_generator,
CreateGenerator(options, options.hash_factory,
options.signing_claim_signer));
ABSL_ASSIGN_OR_RETURN(auto template_generator,
CreateGenerator(options, template_hash_factory.get(),
options.template_claim_signer));
return std::make_unique<DualModeManifestStoreGenerator>(
std::move(signing_generator), std::move(template_generator),
std::move(template_hash_factory));
}
} // namespace credentio