blob: de55e1ba791972b49e83a2bbc55145148cb9df1e [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "arc/keymaster/context/chaps_crypto_operation.h"
#include <chaps/pkcs11/cryptoki.h>
#include "arc/keymaster/context/chaps_client.h"
#include "arc/keymaster/context/context_adaptor.h"
namespace arc {
namespace keymaster {
namespace context {
constexpr MechanismDescription kCkmRsaPkcsSign = {
OperationType::kSign, Algorithm::kRsa, Digest::kNone, Padding ::kPkcs1,
BlockMode::kNone};
constexpr MechanismDescription kCkmSha256RsaPkcsSign = {
OperationType::kSign, Algorithm::kRsa, Digest::kSha256, Padding ::kPkcs1,
BlockMode::kNone};
ChapsCryptoOperation::ChapsCryptoOperation(
base::WeakPtr<ContextAdaptor> context_adaptor,
const std::string& label,
const brillo::Blob& id)
: context_adaptor_(context_adaptor), label_(label), id_(id) {}
ChapsCryptoOperation::~ChapsCryptoOperation() = default;
bool ChapsCryptoOperation::IsSupportedMechanism(
MechanismDescription description) const {
return kCkmRsaPkcsSign == description || kCkmSha256RsaPkcsSign == description;
}
base::Optional<uint64_t> ChapsCryptoOperation::Begin(
MechanismDescription mechanism_description) {
if (!IsSupportedMechanism(mechanism_description)) {
LOG(ERROR) << "Mechanism not implemented for chaps keys: " << description();
return base::nullopt;
}
set_description(mechanism_description);
chaps_ = std::make_unique<ChapsClient>(context_adaptor_);
base::Optional<CK_OBJECT_HANDLE> handle =
chaps_->FindObject(CKO_PRIVATE_KEY, label_, id_);
if (!handle.has_value())
return base::nullopt;
CK_OBJECT_HANDLE key_handle = handle.value();
bool success = false;
if (description() == kCkmSha256RsaPkcsSign) {
success = chaps_->InitializeSignature(CKM_SHA256_RSA_PKCS, key_handle);
} else if (description() == kCkmRsaPkcsSign) {
success = chaps_->InitializeSignature(CKM_RSA_PKCS, key_handle);
} else {
LOG(ERROR) << "Unsupported operation " << description();
}
return success ? chaps_->session_handle() : base::nullopt;
}
base::Optional<brillo::Blob> ChapsCryptoOperation::Update(
const brillo::Blob& input) {
switch (description().type) {
case OperationType::kSign:
return chaps_->UpdateSignature(input)
? base::Optional<brillo::Blob>(brillo::Blob())
: base::nullopt;
case OperationType::kUnsupported:
return base::nullopt;
}
}
base::Optional<brillo::Blob> ChapsCryptoOperation::Finish() {
base::Optional<brillo::Blob> result;
switch (description().type) {
case OperationType::kSign:
result = chaps_->FinalizeSignature();
break;
case OperationType::kUnsupported:
result = base::nullopt;
break;
}
chaps_.reset();
return result;
}
bool ChapsCryptoOperation::Abort() {
chaps_.reset();
return true;
}
} // namespace context
} // namespace keymaster
} // namespace arc