string keymasterAuthorName);
/**
+ * Parses a hardware authentication token blob to extract the details needed to determine if the
+ * token is applicable to a given keymaster operation. This method is intended to be
+ * implemented by the HAL, without requiring a call into the trusted hardware. It is not
+ * necessary for this method to verify that the values in the blob are correct.
+ *
+ * @param token The token blob provided by the authentication app.
+ *
+ * @return error ErrorCode::OK or, if the blob is invalid, ErrorCode::INVALD_ARGUMENT if the
+ * blob is the wrong size, the wrong version, or incorrectly structured.
+ *
+ * @return tokenInfo Information extracted from the auth token.
+ */
+ parseHardwareAuthToken(vec<uint8_t> token)
+ generates(ErrorCode error, HardwareAuthTokenInfo tokenInfo);
+
+ /**
* Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed
* not to be the only source of entropy used, and the mixing function is required to be secure,
* in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
using ::keymaster::SoftKeymasterDevice;
+namespace {
+
class SoftwareOnlyHidlKeymasterEnforcement : public ::keymaster::KeymasterEnforcement {
public:
SoftwareOnlyHidlKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
std::unique_ptr<::keymaster::KeymasterEnforcement> enforcement_;
};
-static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
return rc;
}
-static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
}
}
+template <typename IntType, uint32_t byteOrder> struct choose_ntoh;
+
+template <typename IntType> struct choose_ntoh<IntType, __ORDER_LITTLE_ENDIAN__> {
+ inline static IntType ntoh(const IntType& value) {
+ IntType result = 0;
+ const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
+ unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
+ for (int i = sizeof(IntType) - 1; i >= 0; --i) {
+ *(outbytes++) = inbytes[i];
+ }
+ return result;
+ }
+};
+
+template <typename IntType> struct choose_ntoh<IntType, __ORDER_BIG_ENDIAN__> {
+ inline static IntType hton(const IntType& value) { return value; }
+};
+
+template <typename IntType> inline IntType ntoh(const IntType& value) {
+ return choose_ntoh<IntType, __BYTE_ORDER__>::ntoh(value);
+}
+
+} // anonymous namespace
+
KeymasterDevice::~KeymasterDevice() {
if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
}
return Void();
}
+Return<void> KeymasterDevice::parseHardwareAuthToken(const hidl_vec<uint8_t>& token,
+ parseHardwareAuthToken_cb _hidl_cb) {
+ HardwareAuthTokenInfo parsedToken;
+ if (token.size() != sizeof(hw_auth_token_t)) {
+ ALOGE("Received auth token of length %zu, expected %zu", token.size(),
+ sizeof(hw_auth_token_t));
+ _hidl_cb(ErrorCode::INVALID_ARGUMENT, parsedToken);
+ return Void();
+ }
+
+ const hw_auth_token_t* authToken = reinterpret_cast<const hw_auth_token_t*>(token.data());
+ if (authToken->version != 0) {
+ ALOGE("Auth token version %u, expected version ", authToken->version);
+ _hidl_cb(ErrorCode::INVALID_ARGUMENT, parsedToken);
+ return Void();
+ }
+
+ parsedToken.challenge = authToken->challenge;
+ parsedToken.userId = authToken->user_id;
+ parsedToken.authenticatorId = authToken->authenticator_id;
+ parsedToken.authenticatorType =
+ static_cast<HardwareAuthenticatorType>(ntoh(authToken->authenticator_type));
+ parsedToken.timestamp = ntoh(authToken->timestamp);
+
+ _hidl_cb(ErrorCode::OK, parsedToken);
+ return Void();
+}
+
Return<ErrorCode> KeymasterDevice::addRngEntropy(const hidl_vec<uint8_t>& data) {
if (!data.size()) return ErrorCode::OK;
return legacy_enum_conversion(
};
/**
- * Data used to prove successful authentication.
+ * Data used to describe an authentication. This data is retrieved from an authentication token by
+ * calling the parseHardwareAuthToken method of the HAL.
*/
-struct HardwareAuthToken {
+struct HardwareAuthTokenInfo {
uint64_t challenge;
- uint64_t userId; // Secure User ID, not Android user ID.
- uint64_t authenticatorId; // Secure authenticator ID.
- uint32_t authenticatorType; // HardwareAuthenticatorType, in network order.
- uint64_t timestamp; // In network order.
- uint8_t[32] hmac; // HMAC is computed over 0 || challenge || user_id ||
- // authenticator_id || authenticator_type || timestamp, with a
- // prefixed 0 byte (which was a version field in Keymaster1 and
- // Keymaster2) and the fields packed (no padding; so you probably
- // can't just compute over the bytes of the struct).
+ uint64_t userId; // Secure User ID, not Android user ID.
+ uint64_t authenticatorId; // Secure authenticator ID.
+ HardwareAuthenticatorType authenticatorType;
+ uint64_t timestamp;
};
enum SecurityLevel : uint32_t {