kmsp11/util/status_utils.cc (62 lines of code) (raw):
// Copyright 2021 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
//
// http://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 "kmsp11/util/status_utils.h"
#include <cstring>
#include <optional>
#include <string>
#include "absl/status/status_payload_printer.h"
#include "absl/strings/cord.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_format.h"
#include "common/status_details.pb.h"
#include "common/status_utils.h"
#include "glog/logging.h"
namespace cloud_kms::kmsp11 {
namespace {
// The URL we'll use for storing a custom payload in the status.
// Notes on the naming convention are at
// https://github.com/abseil/abseil-cpp/blob/bf6166a635ab57fe0559b00dcd3ff09a8c42de2e/absl/status/status.h#L149
constexpr std::string_view kTypeUrl =
"type.googleapis.com/kmsp11.StatusDetails";
CK_RV ExtractRvFromCord(const absl::Cord& cord) {
std::string payload(cord);
StatusDetails details;
if (!details.ParseFromString(payload)) {
// It doesn't really make sense to return an error status from a function
// that is itself processing an error status. Log a warning instead.
LOG(WARNING) << "status payload of type " << kTypeUrl << " with payload '"
<< absl::BytesToHexString(payload)
<< "' could not be parsed as a StatusDetails";
}
return details.rv();
}
std::optional<std::string> PrintPayload(std::string_view type_url,
const absl::Cord& content) {
if (type_url != kTypeUrl) {
return std::nullopt;
}
return absl::StrFormat("CK_RV=%#x", ExtractRvFromCord(content));
}
} // namespace
void SetErrorRv(absl::Status& status, CK_RV rv) {
static const bool kPayloadPrinterRegistered = [] {
absl::status_internal::SetStatusPayloadPrinter(&PrintPayload);
return true;
}();
CHECK(kPayloadPrinterRegistered);
CHECK(!status.ok()) << "attempting to set rv=" << rv << " for status OK";
CHECK(rv != CKR_OK) << "attempting to set rv=0 for status " << status;
StatusDetails details;
details.set_rv(rv);
status.SetPayload(kTypeUrl, absl::Cord(details.SerializeAsString()));
}
CK_RV GetCkRv(const absl::Status& status) {
if (status.ok()) {
return CKR_OK;
}
std::optional<absl::Cord> payload = status.GetPayload(kTypeUrl);
if (!payload.has_value()) {
return kDefaultErrorCkRv;
}
CK_RV rv = ExtractRvFromCord(*payload);
if (rv == CKR_OK) {
LOG(WARNING) << "recovered status details has rv=CKR_OK; falling back to "
"default error code";
return kDefaultErrorCkRv;
}
return rv;
}
} // namespace cloud_kms::kmsp11