| // 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 |