blob: e1950f66daa995c14fa9e9548d3c001dd693913d [file] [log] [blame]
/*
* Copyright 2015 The Android Open Source Project
*
* 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.
*/
#ifndef GATEKEEPER_H_
#define GATEKEEPER_H_
#include <stdint.h>
#include <UniquePtr.h>
#include <hardware/hw_auth_token.h>
#include "gatekeeper_messages.h"
#include "password_handle.h"
namespace gatekeeper {
struct __attribute__((packed)) failure_record_t {
uint64_t secure_user_id;
uint64_t last_checked_timestamp;
uint32_t failure_counter;
};
/**
* Base class for gatekeeper implementations. Provides all functionality except
* the ability to create/access keys and compute signatures. These are left up
* to the platform-specific implementation.
*/
class GateKeeper {
public:
GateKeeper() {}
virtual ~GateKeeper() {}
void Enroll(const EnrollRequest &request, EnrollResponse *response);
void Verify(const VerifyRequest &request, VerifyResponse *response);
protected:
// The following methods are intended to be implemented by concrete subclasses
/**
* Retrieves the key used by GateKeeper::MintAuthToken to sign the payload
* of the AuthToken. This is not cached as is may have changed due to an event such
* as a password change.
*
* Writes the length in bytes of the returned key to length if it is not null.
*
* Ownership of the auth_token_key pointer is maintained by the implementor.
*
* Returns true if the key was successfully fetched.
*
*/
virtual bool GetAuthTokenKey(const uint8_t **auth_token_key, uint32_t *length)
const = 0;
/**
* The key used to sign and verify password data.
*
* MUST be different from the AuthTokenKey.
*
* GetPasswordKey is not const because unlike AuthTokenKey,
* this value can be cached.
*
* Ownership of the password_key pointer is maintained by the implementor.
*
*/
virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) = 0;
/**
* Uses platform-specific routines to compute a signature on the provided password.
*
* This can be implemented as a simple pass-through to ComputeSignature, but is
* available in case handling for password signatures is different from general
* purpose signatures.
*
* Writes the signature_length size signature to the 'signature' pointer.
*/
virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
const uint8_t *key, uint32_t key_length, const uint8_t *password,
uint32_t password_length, salt_t salt) const = 0;
/**
* Retrieves a unique, cryptographically randomly generated buffer for use in password
* hashing, etc.
*
* Assings the random to the random UniquePtr, relinquishing ownership to the caller
*/
virtual void GetRandom(void *random, uint32_t requested_size) const = 0;
/**
* Uses platform-specific routines to compute a signature on the provided message.
*
* Writes the signature_length size signature to the 'signature' pointer.
*/
virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
const uint8_t *key, uint32_t key_length, const uint8_t *message,
const uint32_t length) const = 0;
/**
* Get the time since boot in milliseconds.
*
* Should return 0 on error.
*/
virtual uint64_t GetMillisecondsSinceBoot() const = 0;
/**
* Returns the value of the current failure record for the user.
*
* The failure record should be written to hardware-backed secure storage, such as
* RPMB, if the target device supports it.
*
* If 'secure' is false, password is operating in a fallback mode. Implementations
* may store the failure record in memory or in non-secure storage if this value is false.
*
* Returns true on success, false if failure record cannot be retrieved.
*/
virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record,
bool secure) = 0;
/**
* Initializes or reinitializes the failure record for the current user.
*
* Must be persisted in secure storage if the target device supports it.
*
* If 'secure' is false, password is operating in a fallback mode. Implementations
* may store the failure record in memory or in non-secure storage if this value is false.
*
* Returns true if the failure record was successfully persisted.
*/
virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool secure) = 0;
/*
* Writes the provided failure record to persistent storage.
*
* Must be persisted in secure storage if the target device supports it.
*
* If 'secure' is false, password is operating in a fallback mode. Implementations
* may store the failure record in memory or in non-secure storage if this value is false.
*
* Returns true if record was successfully written.
*/
virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool secure) = 0;
/**
* Computes the amount of time to throttle the user due to the current failure_record
* counter. An implementation is provided by the generic GateKeeper, but may be
* overriden.
*/
virtual uint32_t ComputeRetryTimeout(const failure_record_t *record);
/**
* Returns whether the GateKeeper implementation is backed by hardware.
*/
virtual bool IsHardwareBacked() const = 0;
private:
/**
* Generates a signed attestation of an authentication event and assings
* to auth_token UniquePtr.
* The format is consistent with that of hw_auth_token_t.
* Also returns the length in length if it is not null.
*/
void MintAuthToken(UniquePtr<uint8_t> *auth_token, uint32_t *length, uint64_t timestamp,
secure_id_t user_id, secure_id_t authenticator_id, uint64_t challenge);
/**
* Verifies that handle matches password HMAC'ed with the password_key
*/
bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password);
/**
* Populates password_handle with the data provided and computes HMAC.
*/
bool CreatePasswordHandle(SizedBuffer *password_handle, salt_t salt,
secure_id_t secure_id, secure_id_t authenticator_id, uint8_t handle_version,
const uint8_t *password, uint32_t password_length);
/**
* Increments the counter on the current failure record for the provided user id.
* Sets the last_checked_timestamp to timestamp. Writes the updated record
* to *record if not null.
*
* Returns true if failure record was successfully incremented.
*/
bool IncrementFailureRecord(uint32_t uid, secure_id_t user_id, uint64_t timestamp,
failure_record_t *record, bool secure);
/**
* Determines whether the request is within the current throttle window.
*
* If the system timer has been reset due to a reboot or otherwise, resets
* the throttle window with a base at the current time.
*
* Returns true if the request is in the throttle window.
*/
bool ThrottleRequest(uint32_t uid, uint64_t timestamp,
failure_record_t *record, bool secure, GateKeeperMessage *response);
};
}
#endif // GATEKEEPER_H_