/* * 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 #include #include #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; /** * Verifies that handle matches password HMAC'ed with the password_key */ virtual bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password); 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. */ gatekeeper_error_t MintAuthToken(SizedBuffer *auth_token, uint64_t timestamp, secure_id_t user_id, secure_id_t authenticator_id, uint64_t challenge); /** * 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 SizedBuffer & password); /** * 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_