blob: 703dfb76bb6a1af9567545eb5b1708280620e538 [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_operation.h"
#include <iterator>
#include <base/bind.h>
#include <base/logging.h>
#include <base/no_destructor.h>
#include "cryptohome/key_challenge_service.h"
#include "rpc.pb.h" // NOLINT(build/include)
using brillo::Blob;
using brillo::BlobFromString;
using brillo::BlobToString;
namespace cryptohome {
namespace {
// The constant prefix for the salt for challenge-protected credentials (see the
// comment on ChallengeCredentialsOperation::GetSaltConstantPrefix() for
// details).
//
// For extra safety, this constant is made longer than 64 bytes and is
// terminated with a null character, following the safety measures made in TLS
// 1.3: https://tools.ietf.org/html/draft-ietf-tls-tls13-23#section-4.4.3 .
constexpr char kSaltConstantPrefix[] =
"Chrome OS challenge credentials salt Chrome OS challenge credentials "
"salt\0";
static_assert(arraysize(kSaltConstantPrefix) > 64,
"The salt prefix is too short");
static_assert(!kSaltConstantPrefix[arraysize(kSaltConstantPrefix) - 1],
"The salt prefix must terminate with a null character");
// Is called when a response is received for the sent signature challenge
// request.
void OnKeySignatureChallengeResponse(
const ChallengeCredentialsOperation::KeySignatureChallengeCallback&
response_callback,
std::unique_ptr<KeyChallengeResponse> response) {
if (!response) {
LOG(ERROR) << "Signature challenge request failed";
response_callback.Run(nullptr /* signature */);
return;
}
if (!response->has_signature_response_data() ||
!response->signature_response_data().has_signature()) {
LOG(ERROR) << "Signature challenge response is invalid";
response_callback.Run(nullptr /* signature */);
return;
}
response_callback.Run(std::make_unique<Blob>(
BlobFromString(response->signature_response_data().signature())));
}
} // namespace
// static
const brillo::Blob& ChallengeCredentialsOperation::GetSaltConstantPrefix() {
static const base::NoDestructor<brillo::Blob> salt_constant_prefix(
BlobFromString(std::string(std::begin(kSaltConstantPrefix),
std::end(kSaltConstantPrefix))));
// Verify that we correctly converted the static character constant, without
// losing the trailing null character.
CHECK(!salt_constant_prefix->back());
return *salt_constant_prefix;
}
ChallengeCredentialsOperation::~ChallengeCredentialsOperation() {
DCHECK(thread_checker_.CalledOnValidThread());
}
ChallengeCredentialsOperation::ChallengeCredentialsOperation(
KeyChallengeService* key_challenge_service)
: key_challenge_service_(key_challenge_service) {}
void ChallengeCredentialsOperation::MakeKeySignatureChallenge(
const std::string& account_id,
const Blob& public_key_spki_der,
const Blob& data_to_sign,
ChallengeSignatureAlgorithm signature_algorithm,
const KeySignatureChallengeCallback& response_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
AccountIdentifier account_identifier;
account_identifier.set_account_id(account_id);
KeyChallengeRequest challenge_request;
challenge_request.set_challenge_type(
KeyChallengeRequest::CHALLENGE_TYPE_SIGNATURE);
SignatureKeyChallengeRequestData& challenge_request_data =
*challenge_request.mutable_signature_request_data();
challenge_request_data.set_data_to_sign(BlobToString(data_to_sign));
challenge_request_data.set_public_key_spki_der(
BlobToString(public_key_spki_der));
challenge_request_data.set_signature_algorithm(signature_algorithm);
key_challenge_service_->ChallengeKey(
account_identifier, challenge_request,
base::Bind(&OnKeySignatureChallengeResponse, response_callback));
}
} // namespace cryptohome