blob: e37913e770ffcbe4a18acc02d300f372eba1fe1d [file] [log] [blame]
// Copyright 2018 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 "cryptohome/challenge_credentials/challenge_credentials_helper.h"
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include "cryptohome/challenge_credentials/challenge_credentials_operation.h"
#include "cryptohome/key_challenge_service.h"
#include "cryptohome/tpm.h"
#include "cryptohome/username_passkey.h"
using brillo::Blob;
namespace cryptohome {
ChallengeCredentialsHelper::ChallengeCredentialsHelper(
Tpm* tpm,
const Blob& delegate_blob,
const Blob& delegate_secret)
: tpm_(tpm),
delegate_blob_(delegate_blob),
delegate_secret_(delegate_secret) {
DCHECK(tpm_);
}
ChallengeCredentialsHelper::~ChallengeCredentialsHelper() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void ChallengeCredentialsHelper::GenerateNew(
const std::string& account_id,
const KeyData& key_data,
std::unique_ptr<KeyChallengeService> key_challenge_service,
const GenerateNewCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(key_data.type(), KeyData::KEY_TYPE_CHALLENGE_RESPONSE);
DCHECK(!callback.is_null());
CancelRunningOperation();
DCHECK(!key_challenge_service_);
// TODO(emaxx, https://crbug.com/842791): This should generate a salt, request
// its signature, create a sealed secret, generate credentials from the salt
// signature and the secret value.
NOTIMPLEMENTED() << "ChallengeCredentialsHelper::GenerateNew";
}
void ChallengeCredentialsHelper::Decrypt(
const std::string& account_id,
const KeyData& key_data,
const KeysetSignatureChallengeInfo& keyset_challenge_info,
std::unique_ptr<KeyChallengeService> key_challenge_service,
const DecryptCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(key_data.type(), KeyData::KEY_TYPE_CHALLENGE_RESPONSE);
DCHECK(!callback.is_null());
CancelRunningOperation();
DCHECK(!key_challenge_service_);
key_challenge_service_ = std::move(key_challenge_service);
operation_ = std::make_unique<ChallengeCredentialsDecryptOperation>(
key_challenge_service_.get(), tpm_, delegate_blob_, delegate_secret_,
account_id, key_data, keyset_challenge_info, nullptr /* salt_signature */,
base::Bind(&ChallengeCredentialsHelper::OnDecryptCompleted,
base::Unretained(this), callback));
operation_->Start();
}
void ChallengeCredentialsHelper::VerifyKey(
const std::string& account_id,
const KeyData& key_data,
const KeysetSignatureChallengeInfo& keyset_challenge_info,
std::unique_ptr<KeyChallengeService> key_challenge_service,
const VerifyKeyCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(key_data.type(), KeyData::KEY_TYPE_CHALLENGE_RESPONSE);
DCHECK(!callback.is_null());
CancelRunningOperation();
DCHECK(!key_challenge_service_);
// TODO(emaxx, https://crbug.com/842791): This should generate a random
// challenge, request its signature, and verify the signature
// programmatically.
NOTIMPLEMENTED() << "ChallengeCredentialsHelper::VerifyKey";
}
void ChallengeCredentialsHelper::CancelRunningOperation() {
// Destroy the previous Operation before instantiating a new one, to keep the
// resource usage constrained (for example, there must be only one instance of
// SignatureSealingBackend::UnsealingSession at a time).
if (operation_) {
DLOG(INFO) << "Cancelling an old challenge-response credentials operation";
operation_->Abort();
operation_.reset();
// It's illegal for the consumer code to request a new operation in
// immediate response to completion of a previous one.
DCHECK(!operation_);
key_challenge_service_.reset();
}
}
void ChallengeCredentialsHelper::OnDecryptCompleted(
const DecryptCallback& original_callback,
std::unique_ptr<UsernamePasskey> username_passkey) {
DCHECK(thread_checker_.CalledOnValidThread());
CancelRunningOperation();
original_callback.Run(std::move(username_passkey));
}
} // namespace cryptohome