blob: ea9856a9189ca8e005276c874db276ff579b35c9 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRYPTOHOME_AUTH_BLOCKS_PREPARE_TOKEN_H_
#define CRYPTOHOME_AUTH_BLOCKS_PREPARE_TOKEN_H_
#include <memory>
#include <utility>
#include <base/functional/callback.h>
#include <libhwsec-foundation/status/status_chain.h>
#include "cryptohome/auth_factor/type.h"
#include "cryptohome/error/cryptohome_error.h"
#include "cryptohome/key_objects.h"
namespace cryptohome {
// Token that represents an active prepared auth factor. The token can be used
// to terminate the factor, and should automatically do so upon destruction.
//
// Note to subclass implementers: you should include a TerminateOnDestruction
// member in your subclass, to ensure you get the correct destructor behavior.
class PreparedAuthFactorToken {
public:
// Standard callback for function that accept a token. The callback will be
// passed either a valid token on success, or a not-OK status on failure.
using Consumer = base::OnceCallback<void(
CryptohomeStatusOr<std::unique_ptr<PreparedAuthFactorToken>>)>;
// Tokens cannot be copied, since they represent a unique active factor. When
// they are destroyed they will automatically terminate the factor, although
// the Status of this termination is lost in that case.
PreparedAuthFactorToken(AuthFactorType auth_factor_type, PrepareOutput output)
: auth_factor_type_(auth_factor_type), output_(std::move(output)) {}
PreparedAuthFactorToken(const PreparedAuthFactorToken&) = delete;
PreparedAuthFactorToken& operator=(const PreparedAuthFactorToken&) = delete;
virtual ~PreparedAuthFactorToken() = default;
// The type of the auth factor that this token is used for.
AuthFactorType auth_factor_type() const { return auth_factor_type_; }
// The output of the prepare operation.
const PrepareOutput& prepare_output() const { return output_; }
// Terminate the factor. Returns a status reporting any errors with the
// termination process, but note that the factor is considered terminated
// after the call regardless of the result. Subsequent calls to terminate will
// do nothing and return OK.
CryptohomeStatus Terminate() {
if (!terminated_) {
terminated_ = true;
return TerminateAuthFactor();
}
return ::hwsec_foundation::status::OkStatus<error::CryptohomeError>();
}
protected:
// Helpful RAII style class that will ensure that Terminate() is called upon
// destruction. Subclasses should include this as their last member. Making it
// the last member is important because you'll almost certainly want your
// TerminateAuthFactor implementation to be called before any of the other
// member variables are destroyed.
class TerminateOnDestruction {
public:
explicit TerminateOnDestruction(PreparedAuthFactorToken& token)
: token_(token) {}
TerminateOnDestruction(const TerminateOnDestruction&) = delete;
TerminateOnDestruction& operator=(const TerminateOnDestruction&) = delete;
~TerminateOnDestruction() { static_cast<void>(token_.Terminate()); }
private:
PreparedAuthFactorToken& token_;
};
private:
// Override in subclasses to implement termination. Will be called exactly
// once in the lifetime of the token.
virtual CryptohomeStatus TerminateAuthFactor() = 0;
bool terminated_ = false;
const AuthFactorType auth_factor_type_;
const PrepareOutput output_;
};
} // namespace cryptohome
#endif // CRYPTOHOME_AUTH_BLOCKS_PREPARE_TOKEN_H_