blob: d8b49a1794ce40d261ee02c722b1599b6ecbae15 [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 "cose/timestamp_updater.h"
#include <cstdint>
#include <string>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "async/async_context.h"
#include "cose/sig_structure.h"
#include "cose/timestamp_creator.h"
#include "cppbor/cppbor.h"
namespace credentio {
void TimestampUpdater::UpdateTimestamp(
std::string* absl_nonnull encoded_cose_sign1, AsyncContext async_context,
absl::AnyInvocable<void(absl::Status) &&> cb) const {
int64_t original_size = encoded_cose_sign1->size();
auto cose_sign1_or = DecodeCoseSign1TaggedStructure(*encoded_cose_sign1);
if (!cose_sign1_or.ok()) {
AsyncResolver<void>(async_context, std::move(cb))
.Return(cose_sign1_or.status());
return;
}
CoseSign1TaggedStructure cose_sign1 = *std::move(cose_sign1_or);
absl::AnyInvocable<void(absl::StatusOr<std::string>) &&> done_cb =
[cose_sign1 = cose_sign1, original_size, encoded_cose_sign1,
async_context, cb = std::move(cb)](
absl::StatusOr<std::string> status_or_timestamp) mutable {
AsyncResolver<void> resolver(async_context, std::move(cb));
if (!status_or_timestamp.ok()) {
resolver.Return(status_or_timestamp.status());
return;
}
cose_sign1.unprotected_header = {
.sig_tst2 =
TstContainer{
.tst_tokens = {{.val = std::move(*status_or_timestamp)}}},
.pad = "",
};
int64_t delta =
original_size - EncodeCoseSign1TaggedStructure(cose_sign1).size();
if (delta < 0) {
resolver.Return(
absl::InvalidArgumentError("Not enough space for timestamp."));
return;
}
// Adjust padding to account for the encoded size of the `pad` field
// (size zero is encoded with 1 byte).
int64_t pad_size = delta - cppbor::Uint(delta).encodedSize() + 1;
cose_sign1.unprotected_header.pad = std::string(pad_size, '\0');
*encoded_cose_sign1 = EncodeCoseSign1TaggedStructure(cose_sign1);
if (encoded_cose_sign1->size() != original_size) {
resolver.Return(
absl::InternalError("wrong size after updating timestamp"));
return;
}
resolver.Return(absl::OkStatus());
};
timestamp_creator_.CreateTimestamp(
cose_sign1, TimestampCreator::Options{.async_context = async_context},
std::move(done_cb));
}
} // namespace credentio