kmsp11/operation/kms_digesting_verifier.cc (99 lines of code) (raw):
// Copyright 2022 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/operation/kms_digesting_verifier.h"
#include "common/kms_client.h"
#include "common/status_macros.h"
#include "kmsp11/operation/preconditions.h"
#include "kmsp11/util/crypto_utils.h"
#include "kmsp11/util/errors.h"
namespace cloud_kms::kmsp11 {
absl::StatusOr<std::unique_ptr<VerifierInterface>> KmsDigestingVerifier::New(
std::shared_ptr<Object> key,
std::unique_ptr<VerifierInterface> inner_verifier,
const CK_MECHANISM* mechanism) {
ASSIGN_OR_RETURN(const EVP_MD* md, DigestForMechanism(mechanism->mechanism));
return std::unique_ptr<VerifierInterface>(
new KmsDigestingVerifier(std::move(inner_verifier), md));
}
absl::Status KmsDigestingVerifier::Verify(KmsClient* client,
absl::Span<const uint8_t> data,
absl::Span<const uint8_t> signature) {
if (md_ctx_) {
return FailedPreconditionError(
"Verify cannot be used to terminate a multi-part verify operation",
CKR_FUNCTION_FAILED, SOURCE_LOCATION);
}
const size_t md_size = EVP_MD_size(md_);
std::vector<uint8_t> evp_digest(md_size);
unsigned int digest_len;
bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_new());
if (EVP_Digest(data.data(), data.size(), evp_digest.data(), &digest_len, md_,
nullptr) != 1) {
return NewInternalError(
absl::StrFormat(
"failed while computing EVP digest with digest size %d: %s",
md_size, SslErrorToString()),
SOURCE_LOCATION);
}
if (digest_len != md_size) {
return NewInternalError(
absl::StrFormat(
"computed digest has incorrect size (got %d, want %d): %s",
digest_len, md_size, SslErrorToString()),
SOURCE_LOCATION);
}
if (IsRawRsaAlgorithm(object()->algorithm().algorithm)) {
ASSIGN_OR_RETURN(std::vector<uint8_t> digest_info,
BuildRsaDigestInfo(EVP_MD_type(md_), evp_digest));
return inner_verifier_->Verify(client, digest_info, signature);
}
return inner_verifier_->Verify(client, evp_digest, signature);
}
absl::Status KmsDigestingVerifier::VerifyUpdate(
KmsClient* client, absl::Span<const uint8_t> data) {
if (!md_ctx_) {
md_ctx_ = bssl::UniquePtr<EVP_MD_CTX>(EVP_MD_CTX_new());
if (EVP_DigestInit(md_ctx_.get(), md_) != 1) {
return NewInternalError(
absl::StrFormat(
"failed while initializing EVP digest with digest size %d: %s",
EVP_MD_size(md_), SslErrorToString()),
SOURCE_LOCATION);
}
}
if (EVP_DigestUpdate(md_ctx_.get(), data.data(), data.size()) != 1) {
return NewInternalError(
absl::StrCat("failed while updating EVP digest with input data: ",
SslErrorToString()),
SOURCE_LOCATION);
}
return absl::OkStatus();
}
absl::Status KmsDigestingVerifier::VerifyFinal(
KmsClient* client, absl::Span<const uint8_t> signature) {
if (!md_ctx_) {
return FailedPreconditionError(
"VerifyUpdate needs to be called prior to terminating a multi-part "
"verify operation",
CKR_FUNCTION_FAILED, SOURCE_LOCATION);
}
std::vector<uint8_t> evp_digest(EVP_MD_size(md_));
unsigned int digest_len;
if (EVP_DigestFinal(md_ctx_.get(), evp_digest.data(), &digest_len) != 1) {
return NewInternalError(absl::StrCat("failed while finalizing EVP digest: ",
SslErrorToString()),
SOURCE_LOCATION);
}
if (digest_len != EVP_MD_size(md_)) {
return NewInternalError(
absl::StrFormat(
"computed digest has incorrect size (got %d, want %d): %s",
digest_len, EVP_MD_size(md_), SslErrorToString()),
SOURCE_LOCATION);
}
if (IsRawRsaAlgorithm(object()->algorithm().algorithm)) {
ASSIGN_OR_RETURN(std::vector<uint8_t> digest_info,
BuildRsaDigestInfo(EVP_MD_type(md_), evp_digest));
return inner_verifier_->Verify(client, digest_info, signature);
}
return inner_verifier_->Verify(client, evp_digest, signature);
}
} // namespace cloud_kms::kmsp11