Merge "[AWARE] Add global NAN RTT enable/disable flag"
diff --git a/automotive/vehicle/2.0/IVehicle.hal b/automotive/vehicle/2.0/IVehicle.hal
index d962de0..1b1d391 100644
--- a/automotive/vehicle/2.0/IVehicle.hal
+++ b/automotive/vehicle/2.0/IVehicle.hal
@@ -43,7 +43,7 @@
    * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
    * latest available value.
    *
-   * Some properties like AUDIO_VOLUME requires to pass additional data in
+   * Some properties like RADIO_PRESET requires to pass additional data in
    * GET request in VehiclePropValue object.
    *
    * If there is no data available yet, which can happen during initial stage,
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 295ee32..dfbb976 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -40,9 +40,11 @@
         mCameraDeviceNames(cameraDeviceNames) {
     mCameraIdInt = atoi(mCameraId.c_str());
     // Should not reach here as provider also validate ID
-    if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
+    if (mCameraIdInt < 0) {
         ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
         mInitFail = true;
+    } else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
+        ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
     }
 
     mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index a32f410..5c01e35 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -77,6 +77,14 @@
  * Enumeration definitions for the various entries that need them
  */
 
+/** android.control.aeMode enumeration values added since v3.2
+ * @see ANDROID_CONTROL_AE_MODE
+ */
+enum CameraMetadataEnumAndroidControlAeMode :
+        @3.2::CameraMetadataEnumAndroidControlAeMode {
+    ANDROID_CONTROL_AE_MODE_ON_EXTERNAL_FLASH,
+};
+
 /** android.control.captureIntent enumeration values added since v3.2
  * @see ANDROID_CONTROL_CAPTURE_INTENT
  */
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index ed974a5..e9588a7 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -66,6 +66,46 @@
 using ::android::hardware::camera::common::V1_0::CameraMetadataType;
 using ::android::hardware::camera::common::V1_0::Status;
 
+void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new)
+{
+    char cameraId[kMaxCameraIdLen];
+    snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
+    std::string cameraIdStr(cameraId);
+
+    mCameraIds.add(cameraIdStr);
+
+    // initialize mCameraDeviceNames and mOpenLegacySupported
+    mOpenLegacySupported[cameraIdStr] = false;
+    int deviceVersion = mModule->getDeviceVersion(camera_id);
+    auto deviceNamePair = std::make_pair(cameraIdStr,
+                                         getHidlDeviceName(cameraIdStr, deviceVersion));
+    mCameraDeviceNames.add(deviceNamePair);
+    if (cam_new) {
+        mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+    }
+    if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
+            mModule->isOpenLegacyDefined()) {
+        // try open_legacy to see if it actually works
+        struct hw_device_t* halDev = nullptr;
+        int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+        if (ret == 0) {
+            mOpenLegacySupported[cameraIdStr] = true;
+            halDev->close(halDev);
+            deviceNamePair = std::make_pair(cameraIdStr,
+                            getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+            mCameraDeviceNames.add(deviceNamePair);
+            if (cam_new) {
+                mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+            }
+        } else if (ret == -EBUSY || ret == -EUSERS) {
+            // Looks like this provider instance is not initialized during
+            // system startup and there are other camera users already.
+            // Not a good sign but not fatal.
+            ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+        }
+    }
+}
+
 /**
  * static callback forwarding methods from HAL to instance
  */
@@ -75,6 +115,7 @@
         int new_status) {
     CameraProvider* cp = const_cast<CameraProvider*>(
             static_cast<const CameraProvider*>(callbacks));
+    bool found = false;
 
     if (cp == nullptr) {
         ALOGE("%s: callback ops is null", __FUNCTION__);
@@ -92,8 +133,13 @@
             if (cameraIdStr.compare(deviceNamePair.first) == 0) {
                 cp->mCallbacks->cameraDeviceStatusChange(
                         deviceNamePair.second, status);
+                found = true;
             }
         }
+
+        if (!found) {
+            cp->addDeviceNames(camera_id, status, true);
+        }
     }
 }
 
@@ -251,32 +297,8 @@
         snprintf(cameraId, sizeof(cameraId), "%d", i);
         std::string cameraIdStr(cameraId);
         mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
-        mCameraIds.add(cameraIdStr);
 
-        // initialize mCameraDeviceNames and mOpenLegacySupported
-        mOpenLegacySupported[cameraIdStr] = false;
-        int deviceVersion = mModule->getDeviceVersion(i);
-        mCameraDeviceNames.add(
-                std::make_pair(cameraIdStr,
-                               getHidlDeviceName(cameraIdStr, deviceVersion)));
-        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
-                mModule->isOpenLegacyDefined()) {
-            // try open_legacy to see if it actually works
-            struct hw_device_t* halDev = nullptr;
-            int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
-            if (ret == 0) {
-                mOpenLegacySupported[cameraIdStr] = true;
-                halDev->close(halDev);
-                mCameraDeviceNames.add(
-                        std::make_pair(cameraIdStr,
-                                getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)));
-            } else if (ret == -EBUSY || ret == -EUSERS) {
-                // Looks like this provider instance is not initialized during
-                // system startup and there are other camera users already.
-                // Not a good sign but not fatal.
-                ALOGW("%s: open_legacy try failed!", __FUNCTION__);
-            }
-        }
+        addDeviceNames(i);
     }
 
     return false; // mInitFailed
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 4980711..2cf251e 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -112,6 +112,9 @@
         const struct camera_module_callbacks* callbacks,
         const char* camera_id,
         int new_status);
+
+    void addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT,
+                        bool cam_new = false);
 };
 
 extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name);
diff --git a/health/2.0/IHealthInfoCallback.hal b/health/2.0/IHealthInfoCallback.hal
index 737ea72..15352ee 100644
--- a/health/2.0/IHealthInfoCallback.hal
+++ b/health/2.0/IHealthInfoCallback.hal
@@ -16,8 +16,6 @@
 
 package android.hardware.health@2.0;
 
-import @1.0::HealthInfo;
-
 /**
  * IHealthInfoCallback is the callback interface to
  * {@link IHealthInfoBus.registerCallback}.
@@ -28,5 +26,5 @@
      * registered callbacks after health info changes.
      * @param info the updated HealthInfo
      */
-    oneway healthInfoChanged(@1.0::HealthInfo info);
+    oneway healthInfoChanged(HealthInfo info);
 };
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index b1227a3..7a3e650 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -155,10 +155,28 @@
     return Result::SUCCESS;
 }
 
-void Health::notifyListeners(const HealthInfo& info) {
+void Health::notifyListeners(HealthInfo* healthInfo) {
+    std::vector<StorageInfo> info;
+    get_storage_info(info);
+
+    std::vector<DiskStats> stats;
+    get_disk_stats(stats);
+
+    int32_t currentAvg = 0;
+
+    struct BatteryProperty prop;
+    status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
+    if (ret == OK) {
+        currentAvg = static_cast<int32_t>(prop.valueInt64);
+    }
+
+    healthInfo->batteryCurrentAverage = currentAvg;
+    healthInfo->diskStats = stats;
+    healthInfo->storageInfos = info;
+
     std::lock_guard<std::mutex> _lock(callbacks_lock_);
     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
-        auto ret = (*it)->healthInfoChanged(info);
+        auto ret = (*it)->healthInfoChanged(*healthInfo);
         if (!ret.isOk() && ret.isDeadObject()) {
             it = callbacks_.erase(it);
         } else {
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index fc86789..134cdc6 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -22,7 +22,6 @@
 namespace implementation {
 
 using V1_0::BatteryStatus;
-using V1_0::HealthInfo;
 
 using ::android::hidl::base::V1_0::IBase;
 
@@ -38,7 +37,7 @@
     Health(struct healthd_config* c);
 
     // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
-    void notifyListeners(const HealthInfo& info);
+    void notifyListeners(HealthInfo* info);
 
     // Methods from IHealth follow.
     Return<Result> registerCallback(const sp<IHealthInfoCallback>& callback) override;
diff --git a/health/2.0/libhealthhalutils/Android.bp b/health/2.0/libhealthhalutils/Android.bp
index 1bd934b..5686520 100644
--- a/health/2.0/libhealthhalutils/Android.bp
+++ b/health/2.0/libhealthhalutils/Android.bp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+// Convenience library for (hwbinder) clients to choose the correct health
+// service instance.
 cc_library_static {
     name: "libhealthhalutils",
     srcs: ["HealthHalUtils.cpp"],
diff --git a/health/2.0/libstoragehealthdefault/Android.bp b/health/2.0/libstoragehealthdefault/Android.bp
index 986e1ef..cef04fe 100644
--- a/health/2.0/libstoragehealthdefault/Android.bp
+++ b/health/2.0/libstoragehealthdefault/Android.bp
@@ -1,5 +1,22 @@
-// Copyright 2018 The Android Open Source Project
+/*
+ * Copyright (C) 2018 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.
+ */
 
+// Default implementation for (passthrough) clients that statically links to
+// android.hardware.health@2.0-impl but do no query for storage related
+// information.
 cc_library_static {
     srcs: ["StorageHealthDefault.cpp"],
     name: "libhealthstoragedefault",
diff --git a/health/2.0/types.hal b/health/2.0/types.hal
index c74076e..fe33c88 100644
--- a/health/2.0/types.hal
+++ b/health/2.0/types.hal
@@ -141,7 +141,7 @@
     /**
      * Average battery current in uA. Will be 0 if unsupported.
      */
-    int64_t batteryCurrentAverage;
+    int32_t batteryCurrentAverage;
     /**
      * Disk Statistics. Will be an empty vector if unsupported.
      */
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index 85dab44..972bc7f 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -68,7 +68,7 @@
 
 class Callback : public IHealthInfoCallback {
    public:
-    Return<void> healthInfoChanged(const V1_0::HealthInfo&) override {
+    Return<void> healthInfoChanged(const HealthInfo&) override {
         std::lock_guard<std::mutex> lock(mMutex);
         mInvoked = true;
         mInvokedNotify.notify_all();
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index 748fed3..6b8dcdc 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -26,11 +26,18 @@
         "attestation_record.cpp",
         "authorization_set.cpp",
         "key_param_output.cpp",
+        "Keymaster3.cpp",
+        "Keymaster4.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
+        "android.hardware.keymaster@3.0",
         "android.hardware.keymaster@4.0",
+        "libbase",
         "libcrypto",
+        "libhardware",
         "libhidlbase",
+        "libhidltransport",
+        "libutils",
     ]
 }
diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.0/support/Keymaster3.cpp
new file mode 100644
index 0000000..6dfe85b
--- /dev/null
+++ b/keymaster/4.0/support/Keymaster3.cpp
@@ -0,0 +1,325 @@
+/*
+ **
+ ** Copyright 2017, 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.
+ */
+
+#include <keymasterV4_0/Keymaster3.h>
+
+#include <android-base/logging.h>
+#include <hardware/hw_auth_token.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using android::hardware::details::StatusOf;
+
+namespace {
+
+ErrorCode convert(V3_0::ErrorCode error) {
+    return static_cast<ErrorCode>(error);
+}
+
+V3_0::KeyPurpose convert(KeyPurpose purpose) {
+    return static_cast<V3_0::KeyPurpose>(purpose);
+}
+
+V3_0::KeyFormat convert(KeyFormat purpose) {
+    return static_cast<V3_0::KeyFormat>(purpose);
+}
+
+V3_0::KeyParameter convert(const KeyParameter& param) {
+    V3_0::KeyParameter converted;
+    converted.tag = static_cast<V3_0::Tag>(param.tag);
+    static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
+    memcpy(&converted.f, &param.f, sizeof(param.f));
+    converted.blob = param.blob;
+    return converted;
+}
+
+KeyParameter convert(const V3_0::KeyParameter& param) {
+    KeyParameter converted;
+    converted.tag = static_cast<Tag>(param.tag);
+    static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
+    memcpy(&converted.f, &param.f, sizeof(param.f));
+    converted.blob = param.blob;
+    return converted;
+}
+
+hidl_vec<V3_0::KeyParameter> convert(const hidl_vec<KeyParameter>& params) {
+    hidl_vec<V3_0::KeyParameter> converted(params.size());
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    return converted;
+}
+
+hidl_vec<KeyParameter> convert(const hidl_vec<V3_0::KeyParameter>& params) {
+    hidl_vec<KeyParameter> converted(params.size());
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    return converted;
+}
+
+template <typename T, typename OutIter>
+inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+    const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+    return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+constexpr size_t kHmacSize = 32;
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
+    static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                          sizeof(token.timestamp) + kHmacSize ==
+                      sizeof(hw_auth_token_t),
+                  "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+    hidl_vec<uint8_t> result;
+    result.resize(sizeof(hw_auth_token_t));
+    auto pos = result.begin();
+    *pos++ = 0;  // Version byte
+    pos = copy_bytes_to_iterator(token.challenge, pos);
+    pos = copy_bytes_to_iterator(token.userId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+    auto auth_type = htonl(static_cast<uint32_t>(token.authenticatorType));
+    pos = copy_bytes_to_iterator(auth_type, pos);
+    auto timestamp = htonq(token.timestamp);
+    pos = copy_bytes_to_iterator(timestamp, pos);
+    if (token.mac.size() != kHmacSize) {
+        std::fill(pos, pos + kHmacSize, 0);
+    } else {
+        std::copy(token.mac.begin(), token.mac.end(), pos);
+    }
+
+    return result;
+}
+
+hidl_vec<V3_0::KeyParameter> convertAndAddAuthToken(const hidl_vec<KeyParameter>& params,
+                                                    const HardwareAuthToken& authToken) {
+    hidl_vec<V3_0::KeyParameter> converted(params.size() + 1);
+    for (size_t i = 0; i < params.size(); ++i) {
+        converted[i] = convert(params[i]);
+    }
+    converted[params.size()].tag = V3_0::Tag::AUTH_TOKEN;
+    converted[params.size()].blob = authToken2HidlVec(authToken);
+
+    return converted;
+}
+
+KeyCharacteristics convert(const V3_0::KeyCharacteristics& chars) {
+    KeyCharacteristics converted;
+    converted.hardwareEnforced = convert(chars.teeEnforced);
+    converted.softwareEnforced = convert(chars.softwareEnforced);
+    return converted;
+}
+
+}  // namespace
+
+void Keymaster3::getVersionIfNeeded() {
+    if (haveVersion_) return;
+
+    auto rc = km3_dev_->getHardwareFeatures(
+        [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
+            bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
+            const hidl_string& keymasterAuthorName) {
+            securityLevel_ =
+                isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE;
+            supportsEllipticCurve_ = supportsEllipticCurve;
+            supportsSymmetricCryptography_ = supportsSymmetricCryptography;
+            supportsAttestation_ = supportsAttestation;
+            supportsAllDigests_ = supportsAllDigests;
+            keymasterName_ = keymasterName;
+            authorName_ = keymasterAuthorName;
+        });
+
+    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware features";
+
+    if (securityLevel_ == SecurityLevel::SOFTWARE) {
+        majorVersion_ = 3;
+    } else if (supportsAttestation_) {
+        majorVersion_ = 3;  // Could be 2, doesn't matter.
+    } else if (supportsSymmetricCryptography_) {
+        majorVersion_ = 1;
+    } else {
+        majorVersion_ = 0;
+    }
+}
+
+Keymaster::VersionResult Keymaster3::halVersion() {
+    getVersionIfNeeded();
+    return {ErrorCode::OK, majorVersion_, securityLevel_, supportsEllipticCurve_};
+}
+
+Return<void> Keymaster3::getHardwareInfo(Keymaster3::getHardwareInfo_cb _hidl_cb) {
+    getVersionIfNeeded();
+    _hidl_cb(securityLevel_, keymasterName_ + " (wrapped by keystore::Keymaster3)", authorName_);
+    return Void();
+}
+
+Return<ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    auto rc = km3_dev_->addRngEntropy(data);
+    if (!rc.isOk()) {
+        return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    }
+    return convert(rc);
+}
+
+Return<void> Keymaster3::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                     generateKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+                  const V3_0::KeyCharacteristics& characteristics) {
+        _hidl_cb(convert(error), keyBlob, convert(characteristics));
+    };
+    auto rc = km3_dev_->generateKey(convert(keyParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                               const hidl_vec<uint8_t>& clientId,
+                                               const hidl_vec<uint8_t>& appData,
+                                               getKeyCharacteristics_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const V3_0::KeyCharacteristics& chars) {
+        _hidl_cb(convert(error), convert(chars));
+    };
+
+    auto rc = km3_dev_->getKeyCharacteristics(keyBlob, clientId, appData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                                   const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+                  const V3_0::KeyCharacteristics& chars) {
+        _hidl_cb(convert(error), keyBlob, convert(chars));
+    };
+    auto rc = km3_dev_->importKey(convert(params), convert(keyFormat), keyData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                                   const hidl_vec<uint8_t>& clientId,
+                                   const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& keyMaterial) {
+        _hidl_cb(convert(error), keyMaterial);
+    };
+    auto rc = km3_dev_->exportKey(convert(exportFormat), keyBlob, clientId, appData, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                   const hidl_vec<KeyParameter>& attestParams,
+                                   attestKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
+        _hidl_cb(convert(error), certChain);
+    };
+    auto rc = km3_dev_->attestKey(keyToAttest, convert(attestParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                    const hidl_vec<KeyParameter>& upgradeParams,
+                                    upgradeKey_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+        _hidl_cb(convert(error), upgradedKeyBlob);
+    };
+    auto rc = km3_dev_->upgradeKey(keyBlobToUpgrade, convert(upgradeParams), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    auto rc = km3_dev_->deleteKey(keyBlob);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<ErrorCode> Keymaster3::deleteAllKeys() {
+    auto rc = km3_dev_->deleteAllKeys();
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<ErrorCode> Keymaster3::destroyAttestationIds() {
+    auto rc = km3_dev_->destroyAttestationIds();
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+Return<void> Keymaster3::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                               const hidl_vec<KeyParameter>& inParams,
+                               const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<V3_0::KeyParameter>& outParams,
+                  OperationHandle operationHandle) {
+        _hidl_cb(convert(error), convert(outParams), operationHandle);
+    };
+
+    auto rc =
+        km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                                const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                                const VerificationToken& /* verificationToken */,
+                                update_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, uint32_t inputConsumed,
+                  const hidl_vec<V3_0::KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+        _hidl_cb(convert(error), inputConsumed, convert(outParams), output);
+    };
+
+    auto rc =
+        km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<void> Keymaster3::finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                                const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                                const HardwareAuthToken& authToken,
+                                const VerificationToken& /* verificationToken */,
+                                finish_cb _hidl_cb) {
+    auto cb = [&](V3_0::ErrorCode error, const hidl_vec<V3_0::KeyParameter>& outParams,
+                  const hidl_vec<uint8_t>& output) {
+        _hidl_cb(convert(error), convert(outParams), output);
+    };
+
+    auto rc = km3_dev_->finish(operationHandle, convertAndAddAuthToken(inParams, authToken), input,
+                               signature, cb);
+    rc.isOk();  // move ctor prereq
+    return rc;
+}
+
+Return<ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
+    auto rc = km3_dev_->abort(operationHandle);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    return convert(rc);
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/Keymaster4.cpp b/keymaster/4.0/support/Keymaster4.cpp
new file mode 100644
index 0000000..fdf78ae
--- /dev/null
+++ b/keymaster/4.0/support/Keymaster4.cpp
@@ -0,0 +1,48 @@
+/*
+**
+** Copyright 2017, 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.
+*/
+
+#include <keymasterV4_0/Keymaster4.h>
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+void Keymaster4::getVersionIfNeeded() {
+    if (haveVersion_) return;
+
+    auto rc = dev_->getHardwareInfo([&](SecurityLevel securityLevel, auto...) {
+        securityLevel_ = securityLevel;
+        haveVersion_ = true;
+    });
+
+    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
+}
+
+Keymaster::VersionResult Keymaster4::halVersion() {
+    getVersionIfNeeded();
+    return {ErrorCode::OK, halMajorVersion(), securityLevel_, true};
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
new file mode 100644
index 0000000..2686fcd
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -0,0 +1,58 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+/**
+ * Keymaster abstracts the underlying V4_0::IKeymasterDevice.  There is one implementation
+ * (Keymaster4) which is a trivial passthrough and one that wraps a V3_0::IKeymasterDevice.
+ *
+ * The reason for adding this additional layer, rather than simply using the latest HAL directly and
+ * subclassing it to wrap any older HAL, is because this provides a place to put additional methods
+ * which clients can use when they need to distinguish between different underlying HAL versions,
+ * while still having to use only the latest interface.
+ */
+class Keymaster : public IKeymasterDevice {
+   public:
+    virtual ~Keymaster() {}
+
+    struct VersionResult {
+        ErrorCode error;
+        uint8_t majorVersion;
+        SecurityLevel securityLevel;
+        bool supportsEc;
+    };
+
+    virtual VersionResult halVersion() = 0;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
new file mode 100644
index 0000000..051e570
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
@@ -0,0 +1,129 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
+#include "Keymaster.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using IKeymaster3Device = ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::details::return_status;
+
+class Keymaster3 : public Keymaster {
+   public:
+    using WrappedIKeymasterDevice = IKeymaster3Device;
+    Keymaster3(sp<IKeymaster3Device> km3_dev) : km3_dev_(km3_dev), haveVersion_(false) {}
+
+    VersionResult halVersion() override;
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb);
+
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>&,
+                                   computeSharedHmac_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<void> verifyAuthorization(uint64_t, const hidl_vec<KeyParameter>&,
+                                     const HardwareAuthToken&,
+                                     verifyAuthorization_cb _hidl_cb) override {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        return Void();
+    }
+
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>&, const hidl_vec<uint8_t>&,
+                                  const hidl_vec<uint8_t>&, importWrappedKey_cb _hidl_cb) {
+        _hidl_cb(ErrorCode::UNIMPLEMENTED, {}, {});
+        return Void();
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override;
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+   private:
+    void getVersionIfNeeded();
+
+    sp<IKeymaster3Device> km3_dev_;
+
+    bool haveVersion_;
+    uint8_t majorVersion_;
+    SecurityLevel securityLevel_;
+    bool supportsEllipticCurve_;
+    bool supportsSymmetricCryptography_;
+    bool supportsAttestation_;
+    bool supportsAllDigests_;
+    std::string keymasterName_;
+    std::string authorName_;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
new file mode 100644
index 0000000..ffddcac
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
@@ -0,0 +1,153 @@
+/*
+ **
+ ** Copyright 2017, 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 HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
+
+#include "Keymaster.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using android::sp;
+using IKeymaster4Device = ::android::hardware::keymaster::V4_0::IKeymasterDevice;
+
+class Keymaster4 : public Keymaster {
+   public:
+    using WrappedIKeymasterDevice = IKeymaster4Device;
+    Keymaster4(sp<IKeymasterDevice> km4_dev) : haveVersion_(false), dev_(km4_dev) {}
+
+    uint8_t halMajorVersion() { return 4; }
+
+    VersionResult halVersion() override;
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
+        return dev_->getHardwareInfo(_hidl_cb);
+    }
+
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+        return dev_->getHmacSharingParameters(_hidl_cb);
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+                                   computeSharedHmac_cb _hidl_cb) override {
+        return dev_->computeSharedHmac(params, _hidl_cb);
+    }
+
+    Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
+                                     const HardwareAuthToken& authToken,
+                                     verifyAuthorization_cb _hidl_cb) override {
+        return dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
+        return dev_->addRngEntropy(data);
+    }
+
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override {
+        return dev_->generateKey(keyParams, _hidl_cb);
+    }
+
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override {
+        return dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
+        return dev_->importKey(params, keyFormat, keyData, _hidl_cb);
+    }
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
+                                  const hidl_vec<uint8_t>& maskingKey,
+                                  importWrappedKey_cb _hidl_cb) {
+        return dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey, _hidl_cb);
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override {
+        return dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override {
+        return dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
+    }
+
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override {
+        return dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
+    }
+
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
+        return dev_->deleteKey(keyBlob);
+    }
+
+    Return<ErrorCode> deleteAllKeys() override { return dev_->deleteAllKeys(); }
+
+    Return<ErrorCode> destroyAttestationIds() override { return dev_->destroyAttestationIds(); }
+
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override {
+        return dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
+    }
+
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override {
+        return dev_->update(operationHandle, inParams, input, authToken, verificationToken,
+                            _hidl_cb);
+    }
+
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
+        return dev_->finish(operationHandle, inParams, input, signature, authToken,
+                            verificationToken, _hidl_cb);
+    }
+
+    Return<ErrorCode> abort(uint64_t operationHandle) override {
+        return dev_->abort(operationHandle);
+    }
+
+   private:
+    void getVersionIfNeeded();
+
+    bool haveVersion_;
+    SecurityLevel securityLevel_;
+    sp<IKeymaster4Device> dev_;
+};
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 3c3063c..e705d66 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -18,6 +18,8 @@
     name: "VtsHalKeymasterV4_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
+        "HmacKeySharingTest.cpp",
+        "KeymasterHidlTest.cpp",
         "keymaster_hidl_hal_test.cpp",
     ],
     static_libs: [
diff --git a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
new file mode 100644
index 0000000..96c47a8
--- /dev/null
+++ b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "KeymasterHidlTest.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace test {
+
+/**
+ * HmacKeySharingTest extends KeymasterHidlTest with some utilities that make writing HMAC sharing
+ * tests easier.
+ */
+class HmacKeySharingTest : public KeymasterHidlTest {
+   protected:
+    struct GetParamsResult {
+        ErrorCode error;
+        HmacSharingParameters params;
+        auto tie() { return std::tie(error, params); }
+    };
+
+    struct ComputeHmacResult {
+        ErrorCode error;
+        HidlBuf sharing_check;
+        auto tie() { return std::tie(error, sharing_check); }
+    };
+
+    using KeymasterVec = std::vector<sp<IKeymasterDevice>>;
+    using ByteString = std::basic_string<uint8_t>;
+    // using NonceVec = std::vector<HidlBuf>;
+
+    GetParamsResult getHmacSharingParameters(IKeymasterDevice& keymaster) {
+        GetParamsResult result;
+        EXPECT_TRUE(keymaster
+                        .getHmacSharingParameters([&](auto error, auto params) {
+                            result.tie() = std::tie(error, params);
+                        })
+                        .isOk());
+        return result;
+    }
+
+    hidl_vec<HmacSharingParameters> getHmacSharingParameters(const KeymasterVec& keymasters) {
+        std::vector<HmacSharingParameters> paramsVec;
+        for (auto& keymaster : keymasters) {
+            auto result = getHmacSharingParameters(*keymaster);
+            EXPECT_EQ(ErrorCode::OK, result.error);
+            if (result.error == ErrorCode::OK) paramsVec.push_back(std::move(result.params));
+        }
+        return paramsVec;
+    }
+
+    ComputeHmacResult computeSharedHmac(IKeymasterDevice& keymaster,
+                                        const hidl_vec<HmacSharingParameters>& params) {
+        ComputeHmacResult result;
+        EXPECT_TRUE(keymaster
+                        .computeSharedHmac(params,
+                                           [&](auto error, auto params) {
+                                               result.tie() = std::tie(error, params);
+                                           })
+                        .isOk());
+        return result;
+    }
+
+    std::vector<ComputeHmacResult> computeSharedHmac(
+        const KeymasterVec& keymasters, const hidl_vec<HmacSharingParameters>& paramsVec) {
+        std::vector<ComputeHmacResult> resultVec;
+        for (auto& keymaster : keymasters) {
+            resultVec.push_back(computeSharedHmac(*keymaster, paramsVec));
+        }
+        return resultVec;
+    }
+
+    std::vector<ByteString> copyNonces(const hidl_vec<HmacSharingParameters>& paramsVec) {
+        std::vector<ByteString> nonces;
+        for (auto& param : paramsVec) {
+            nonces.emplace_back(param.nonce.data(), param.nonce.size());
+        }
+        return nonces;
+    }
+
+    void verifyResponses(const HidlBuf& expected, const std::vector<ComputeHmacResult>& responses) {
+        for (auto& response : responses) {
+            EXPECT_EQ(ErrorCode::OK, response.error);
+            EXPECT_EQ(expected, response.sharing_check) << "Sharing check values should match.";
+        }
+    }
+};
+
+TEST_F(HmacKeySharingTest, GetParameters) {
+    auto result1 = getHmacSharingParameters(keymaster());
+    EXPECT_EQ(ErrorCode::OK, result1.error);
+
+    auto result2 = getHmacSharingParameters(keymaster());
+    EXPECT_EQ(ErrorCode::OK, result2.error);
+
+    ASSERT_EQ(result1.params.seed, result2.params.seed)
+        << "A given keymaster should always return the same seed.";
+    ASSERT_EQ(result1.params.nonce, result2.params.nonce)
+        << "A given keymaster should always return the same nonce until restart.";
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmac) {
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    auto nonces = copyNonces(params);
+    EXPECT_EQ(all_keymasters().size(), nonces.size());
+    std::sort(nonces.begin(), nonces.end());
+    std::unique(nonces.begin(), nonces.end());
+    EXPECT_EQ(all_keymasters().size(), nonces.size());
+
+    auto responses = computeSharedHmac(all_keymasters(), params);
+    ASSERT_GT(responses.size(), 0U);
+    verifyResponses(responses[0].sharing_check, responses);
+
+    // Do it a second time.  Should get the same answers.
+    params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    ASSERT_GT(responses.size(), 0U);
+    verifyResponses(responses[0].sharing_check, responses);
+}
+
+template <class F>
+class final_action {
+   public:
+    explicit final_action(F f) : f_(move(f)) {}
+    ~final_action() { f_(); }
+
+   private:
+    F f_;
+};
+
+template <class F>
+inline final_action<F> finally(const F& f) {
+    return final_action<F>(f);
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmacCorruptNonce) {
+    // Important: The execution of this test gets the keymaster implementations on the device out of
+    // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
+    // devices, this still has the potential to cause confusion.  To mitigate that, we always
+    // (barring crashes :-/) re-run the unmodified agreement process on our way out.
+    auto fixup_hmac = finally(
+        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeSharedHmac(all_keymasters(), params);
+
+    ASSERT_GT(responses.size(), 0U);
+    HidlBuf correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param, a random byte within the param's nonce, and a random bit within
+    // the byte.  Flip that bit.
+    size_t param_to_tweak = rand() % params.size();
+    uint8_t byte_to_tweak = rand() % sizeof(params[param_to_tweak].nonce);
+    uint8_t bit_to_tweak = rand() % 8;
+    params[param_to_tweak].nonce[byte_to_tweak] ^= (1 << bit_to_tweak);
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                << "Keymaster that provided tweaked param should fail to compute HMAC key";
+        } else {
+            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+            EXPECT_NE(correct_response, responses[i].sharing_check)
+                << "Others should calculate a different HMAC key, due to the tweaked nonce.";
+        }
+    }
+}
+
+TEST_F(HmacKeySharingTest, ComputeSharedHmacCorruptSeed) {
+    // Important: The execution of this test gets the keymaster implementations on the device out of
+    // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
+    // devices, this still has the potential to cause confusion.  To mitigate that, we always
+    // (barring crashes :-/) re-run the unmodified agreement process on our way out.
+    auto fixup_hmac = finally(
+        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+
+    auto params = getHmacSharingParameters(all_keymasters());
+    ASSERT_EQ(all_keymasters().size(), params.size())
+        << "One or more keymasters failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeSharedHmac(all_keymasters(), params);
+
+    ASSERT_GT(responses.size(), 0U);
+    HidlBuf correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param and modify the seed.  We just increase the seed length by 1.  It doesn't
+    // matter what value is in the additional byte; it changes the seed regardless.
+    auto param_to_tweak = rand() % params.size();
+    auto& to_tweak = params[param_to_tweak].seed;
+    to_tweak.resize(to_tweak.size() + 1);
+
+    responses = computeSharedHmac(all_keymasters(), params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                << "Keymaster that provided tweaked param should fail to compute HMAC key ";
+        } else {
+            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+            EXPECT_NE(correct_response, responses[i].sharing_check)
+                << "Others should calculate a different HMAC key, due to the tweaked nonce.";
+        }
+    }
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
new file mode 100644
index 0000000..13b6b2f
--- /dev/null
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "KeymasterHidlTest.h"
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+
+#include <keymasterV4_0/key_param_output.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
+    if (set.size() == 0)
+        os << "(Empty)" << ::std::endl;
+    else {
+        os << "\n";
+        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+    }
+    return os;
+}
+
+namespace test {
+
+sp<IKeymasterDevice> KeymasterHidlTest::keymaster_;
+std::vector<sp<IKeymasterDevice>> KeymasterHidlTest::all_keymasters_;
+uint32_t KeymasterHidlTest::os_version_;
+uint32_t KeymasterHidlTest::os_patch_level_;
+SecurityLevel KeymasterHidlTest::securityLevel_;
+hidl_string KeymasterHidlTest::name_;
+hidl_string KeymasterHidlTest::author_;
+
+void KeymasterHidlTest::SetUpTestCase() {
+    string service_name = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
+    keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
+    ASSERT_NE(keymaster_, nullptr);
+
+    ASSERT_TRUE(keymaster_
+                    ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+                                          const hidl_string& author) {
+                        securityLevel_ = securityLevel;
+                        name_ = name;
+                        author_ = author;
+                    })
+                    .isOk());
+
+    os_version_ = ::keymaster::GetOsVersion();
+    os_patch_level_ = ::keymaster::GetOsPatchlevel();
+
+    auto service_manager = android::hidl::manager::V1_0::IServiceManager::getService();
+    ASSERT_NE(nullptr, service_manager.get());
+
+    all_keymasters_.push_back(keymaster_);
+    service_manager->listByInterface(
+        IKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
+            for (auto& name : names) {
+                if (name == service_name) continue;
+                auto keymaster =
+                    ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(name);
+                ASSERT_NE(keymaster, nullptr);
+                all_keymasters_.push_back(keymaster);
+            }
+        });
+}
+
+ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
+                                         KeyCharacteristics* key_characteristics) {
+    EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
+    EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key.  Test bug.";
+    EXPECT_NE(key_characteristics, nullptr)
+        << "Previous characteristics not deleted before generating key.  Test bug.";
+
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->generateKey(key_desc.hidl_data(),
+                                  [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                      const KeyCharacteristics& hidl_key_characteristics) {
+                                      error = hidl_error;
+                                      *key_blob = hidl_key_blob;
+                                      *key_characteristics = hidl_key_characteristics;
+                                  })
+                    .isOk());
+    // On error, blob & characteristics should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_blob->size());
+        EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                       key_characteristics->hardwareEnforced.size()));
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc) {
+    return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                                       const string& key_material, HidlBuf* key_blob,
+                                       KeyCharacteristics* key_characteristics) {
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
+                                [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                    const KeyCharacteristics& hidl_key_characteristics) {
+                                    error = hidl_error;
+                                    *key_blob = hidl_key_blob;
+                                    *key_characteristics = hidl_key_characteristics;
+                                })
+                    .isOk());
+    // On error, blob & characteristics should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_blob->size());
+        EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                       key_characteristics->hardwareEnforced.size()));
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                                       const string& key_material) {
+    return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
+}
+
+ErrorCode KeymasterHidlTest::ImportWrappedKey(string wrapped_key, string wrapping_key,
+                                              const AuthorizationSet& wrapping_key_desc,
+                                              string masking_key) {
+    ErrorCode error;
+    ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key);
+    EXPECT_TRUE(keymaster_
+                    ->importWrappedKey(HidlBuf(wrapped_key), key_blob_, HidlBuf(masking_key),
+                                       [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                           const KeyCharacteristics& hidl_key_characteristics) {
+                                           error = hidl_error;
+                                           key_blob_ = hidl_key_blob;
+                                           key_characteristics_ = hidl_key_characteristics;
+                                       })
+                    .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, const HidlBuf& key_blob,
+                                       const HidlBuf& client_id, const HidlBuf& app_data,
+                                       HidlBuf* key_material) {
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->exportKey(format, key_blob, client_id, app_data,
+                                [&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
+                                    error = hidl_error_code;
+                                    *key_material = hidl_key_material;
+                                })
+                    .isOk());
+    // On error, blob should be empty.
+    if (error != ErrorCode::OK) {
+        EXPECT_EQ(0U, key_material->size());
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, HidlBuf* key_material) {
+    HidlBuf client_id, app_data;
+    return ExportKey(format, key_blob_, client_id, app_data, key_material);
+}
+
+ErrorCode KeymasterHidlTest::DeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
+    auto rc = keymaster_->deleteKey(*key_blob);
+    if (!keep_key_blob) *key_blob = HidlBuf();
+    if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+    return rc;
+}
+
+ErrorCode KeymasterHidlTest::DeleteKey(bool keep_key_blob) {
+    return DeleteKey(&key_blob_, keep_key_blob);
+}
+
+ErrorCode KeymasterHidlTest::DeleteAllKeys() {
+    ErrorCode error = keymaster_->deleteAllKeys();
+    return error;
+}
+
+void KeymasterHidlTest::CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
+    auto rc = DeleteKey(key_blob, keep_key_blob);
+    EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+}
+
+void KeymasterHidlTest::CheckedDeleteKey() {
+    CheckedDeleteKey(&key_blob_);
+}
+
+ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
+                                                const HidlBuf& app_data,
+                                                KeyCharacteristics* key_characteristics) {
+    ErrorCode error = ErrorCode::UNKNOWN_ERROR;
+    EXPECT_TRUE(
+        keymaster_
+            ->getKeyCharacteristics(
+                key_blob, client_id, app_data,
+                [&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
+                    error = hidl_error, *key_characteristics = hidl_key_characteristics;
+                })
+            .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob,
+                                                KeyCharacteristics* key_characteristics) {
+    HidlBuf client_id, app_data;
+    return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const HidlBuf& key_blob,
+                                   const AuthorizationSet& in_params, AuthorizationSet* out_params,
+                                   OperationHandle* op_handle) {
+    SCOPED_TRACE("Begin");
+    ErrorCode error;
+    OperationHandle saved_handle = *op_handle;
+    EXPECT_TRUE(keymaster_
+                    ->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
+                            [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                                uint64_t hidl_op_handle) {
+                                error = hidl_error;
+                                *out_params = hidl_out_params;
+                                *op_handle = hidl_op_handle;
+                            })
+                    .isOk());
+    if (error != ErrorCode::OK) {
+        // Some implementations may modify *op_handle on error.
+        *op_handle = saved_handle;
+    }
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+                                   AuthorizationSet* out_params) {
+    SCOPED_TRACE("Begin");
+    EXPECT_EQ(kOpHandleSentinel, op_handle_);
+    return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
+}
+
+ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
+    SCOPED_TRACE("Begin");
+    AuthorizationSet out_params;
+    ErrorCode error = Begin(purpose, in_params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Update(OperationHandle op_handle, const AuthorizationSet& in_params,
+                                    const string& input, AuthorizationSet* out_params,
+                                    string* output, size_t* input_consumed) {
+    SCOPED_TRACE("Update");
+    ErrorCode error;
+    EXPECT_TRUE(keymaster_
+                    ->update(op_handle, in_params.hidl_data(), HidlBuf(input), HardwareAuthToken(),
+                             VerificationToken(),
+                             [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
+                                 const hidl_vec<KeyParameter>& hidl_out_params,
+                                 const HidlBuf& hidl_output) {
+                                 error = hidl_error;
+                                 out_params->push_back(AuthorizationSet(hidl_out_params));
+                                 output->append(hidl_output.to_string());
+                                 *input_consumed = hidl_input_consumed;
+                             })
+                    .isOk());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Update(const string& input, string* out, size_t* input_consumed) {
+    SCOPED_TRACE("Update");
+    AuthorizationSet out_params;
+    ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
+                             out, input_consumed);
+    EXPECT_TRUE(out_params.empty());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
+                                    const string& input, const string& signature,
+                                    AuthorizationSet* out_params, string* output) {
+    SCOPED_TRACE("Finish");
+    ErrorCode error;
+    EXPECT_TRUE(
+        keymaster_
+            ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
+                     HardwareAuthToken(), VerificationToken(),
+                     [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                         const HidlBuf& hidl_output) {
+                         error = hidl_error;
+                         *out_params = hidl_out_params;
+                         output->append(hidl_output.to_string());
+                     })
+            .isOk());
+    op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(const string& message, string* output) {
+    SCOPED_TRACE("Finish");
+    AuthorizationSet out_params;
+    string finish_output;
+    ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
+                             "" /* signature */, &out_params, output);
+    if (error != ErrorCode::OK) {
+        return error;
+    }
+    EXPECT_EQ(0U, out_params.size());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Finish(const string& message, const string& signature,
+                                    string* output) {
+    SCOPED_TRACE("Finish");
+    AuthorizationSet out_params;
+    ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
+                             &out_params, output);
+    op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+    if (error != ErrorCode::OK) {
+        return error;
+    }
+    EXPECT_EQ(0U, out_params.size());
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::Abort(OperationHandle op_handle) {
+    SCOPED_TRACE("Abort");
+    auto retval = keymaster_->abort(op_handle);
+    EXPECT_TRUE(retval.isOk());
+    return retval;
+}
+
+void KeymasterHidlTest::AbortIfNeeded() {
+    SCOPED_TRACE("AbortIfNeeded");
+    if (op_handle_ != kOpHandleSentinel) {
+        EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
+        op_handle_ = kOpHandleSentinel;
+    }
+}
+
+ErrorCode KeymasterHidlTest::AttestKey(const HidlBuf& key_blob,
+                                       const AuthorizationSet& attest_params,
+                                       hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+    SCOPED_TRACE("AttestKey");
+    ErrorCode error;
+    auto rc = keymaster_->attestKey(
+        key_blob, attest_params.hidl_data(),
+        [&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
+            error = hidl_error;
+            *cert_chain = hidl_cert_chain;
+        });
+
+    EXPECT_TRUE(rc.isOk()) << rc.description();
+    if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+
+    return error;
+}
+
+ErrorCode KeymasterHidlTest::AttestKey(const AuthorizationSet& attest_params,
+                                       hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+    SCOPED_TRACE("AttestKey");
+    return AttestKey(key_blob_, attest_params, cert_chain);
+}
+
+string KeymasterHidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation,
+                                         const string& message, const AuthorizationSet& in_params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("ProcessMessage");
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
+
+    string unused;
+    AuthorizationSet finish_params;
+    AuthorizationSet finish_out_params;
+    string output;
+    EXPECT_EQ(ErrorCode::OK,
+              Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
+    op_handle_ = kOpHandleSentinel;
+
+    out_params->push_back(begin_out_params);
+    out_params->push_back(finish_out_params);
+    return output;
+}
+
+string KeymasterHidlTest::SignMessage(const HidlBuf& key_blob, const string& message,
+                                      const AuthorizationSet& params) {
+    SCOPED_TRACE("SignMessage");
+    AuthorizationSet out_params;
+    string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return signature;
+}
+
+string KeymasterHidlTest::SignMessage(const string& message, const AuthorizationSet& params) {
+    SCOPED_TRACE("SignMessage");
+    return SignMessage(key_blob_, message, params);
+}
+
+string KeymasterHidlTest::MacMessage(const string& message, Digest digest, size_t mac_length) {
+    SCOPED_TRACE("MacMessage");
+    return SignMessage(
+        key_blob_, message,
+        AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
+}
+
+void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
+                                            const string& expected_mac) {
+    SCOPED_TRACE("CheckHmacTestVector");
+    ASSERT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_NO_AUTH_REQUIRED)
+                            .HmacKey(key.size() * 8)
+                            .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
+                            .Digest(digest),
+                        KeyFormat::RAW, key));
+    string signature = MacMessage(message, digest, expected_mac.size() * 8);
+    EXPECT_EQ(expected_mac, signature)
+        << "Test vector didn't match for key of size " << key.size() << " message of size "
+        << message.size() << " and digest " << digest;
+    CheckedDeleteKey();
+}
+
+void KeymasterHidlTest::CheckAesCtrTestVector(const string& key, const string& nonce,
+                                              const string& message,
+                                              const string& expected_ciphertext) {
+    SCOPED_TRACE("CheckAesCtrTestVector");
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .AesEncryptionKey(key.size() * 8)
+                                           .BlockMode(BlockMode::CTR)
+                                           .Authorization(TAG_CALLER_NONCE)
+                                           .Padding(PaddingMode::NONE),
+                                       KeyFormat::RAW, key));
+
+    auto params = AuthorizationSetBuilder()
+                      .Authorization(TAG_NONCE, nonce.data(), nonce.size())
+                      .BlockMode(BlockMode::CTR)
+                      .Padding(PaddingMode::NONE);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
+    EXPECT_EQ(expected_ciphertext, ciphertext);
+}
+
+void KeymasterHidlTest::CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+                                                 PaddingMode padding_mode, const string& key,
+                                                 const string& iv, const string& input,
+                                                 const string& expected_output) {
+    auto authset = AuthorizationSetBuilder()
+                       .TripleDesEncryptionKey(key.size() * 7)
+                       .BlockMode(block_mode)
+                       .Padding(padding_mode);
+    if (iv.size()) authset.Authorization(TAG_CALLER_NONCE);
+    ASSERT_EQ(ErrorCode::OK, ImportKey(authset, KeyFormat::RAW, key));
+    auto begin_params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
+    if (iv.size()) begin_params.Authorization(TAG_NONCE, iv.data(), iv.size());
+    AuthorizationSet output_params;
+    string output = ProcessMessage(key_blob_, purpose, input, begin_params, &output_params);
+    EXPECT_EQ(expected_output, output);
+}
+
+void KeymasterHidlTest::VerifyMessage(const HidlBuf& key_blob, const string& message,
+                                      const string& signature, const AuthorizationSet& params) {
+    SCOPED_TRACE("VerifyMessage");
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
+
+    string unused;
+    AuthorizationSet finish_params;
+    AuthorizationSet finish_out_params;
+    string output;
+    EXPECT_EQ(ErrorCode::OK,
+              Finish(op_handle_, finish_params, message, signature, &finish_out_params, &output));
+    op_handle_ = kOpHandleSentinel;
+    EXPECT_TRUE(output.empty());
+}
+
+void KeymasterHidlTest::VerifyMessage(const string& message, const string& signature,
+                                      const AuthorizationSet& params) {
+    SCOPED_TRACE("VerifyMessage");
+    VerifyMessage(key_blob_, message, signature, params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const HidlBuf& key_blob, const string& message,
+                                         const AuthorizationSet& in_params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("EncryptMessage");
+    return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params,
+                                         AuthorizationSet* out_params) {
+    SCOPED_TRACE("EncryptMessage");
+    return EncryptMessage(key_blob_, message, params, out_params);
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params) {
+    SCOPED_TRACE("EncryptMessage");
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding, HidlBuf* iv_out) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_EQ(1U, out_params.size());
+    auto ivVal = out_params.GetTagValue(TAG_NONCE);
+    EXPECT_TRUE(ivVal.isOk());
+    *iv_out = ivVal.value();
+    return ciphertext;
+}
+
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding, const HidlBuf& iv_in) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(block_mode)
+                      .Padding(padding)
+                      .Authorization(TAG_NONCE, iv_in);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    return ciphertext;
+}
+
+string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
+                                         const AuthorizationSet& params) {
+    SCOPED_TRACE("DecryptMessage");
+    AuthorizationSet out_params;
+    string plaintext =
+        ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
+    EXPECT_TRUE(out_params.empty());
+    return plaintext;
+}
+
+string KeymasterHidlTest::DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
+    SCOPED_TRACE("DecryptMessage");
+    return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+string KeymasterHidlTest::DecryptMessage(const string& ciphertext, BlockMode block_mode,
+                                         PaddingMode padding_mode, const HidlBuf& iv) {
+    SCOPED_TRACE("DecryptMessage");
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(block_mode)
+                      .Padding(padding_mode)
+                      .Authorization(TAG_NONCE, iv);
+    return DecryptMessage(key_blob_, ciphertext, params);
+}
+
+std::pair<ErrorCode, HidlBuf> KeymasterHidlTest::UpgradeKey(const HidlBuf& key_blob) {
+    std::pair<ErrorCode, HidlBuf> retval;
+    keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
+                           [&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
+                               retval = std::tie(error, upgraded_blob);
+                           });
+    return retval;
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
new file mode 100644
index 0000000..0c73f05
--- /dev/null
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 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 HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <keymaster/keymaster_configuration.h>
+
+#include <keymasterV4_0/authorization_set.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
+
+namespace test {
+
+using ::android::sp;
+using ::std::string;
+
+class HidlBuf : public hidl_vec<uint8_t> {
+    typedef hidl_vec<uint8_t> super;
+
+   public:
+    HidlBuf() {}
+    HidlBuf(const super& other) : super(other) {}
+    HidlBuf(super&& other) : super(std::move(other)) {}
+    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
+
+    HidlBuf& operator=(const super& other) {
+        super::operator=(other);
+        return *this;
+    }
+
+    HidlBuf& operator=(super&& other) {
+        super::operator=(std::move(other));
+        return *this;
+    }
+
+    HidlBuf& operator=(const string& other) {
+        resize(other.size());
+        std::copy(other.begin(), other.end(), begin());
+        return *this;
+    }
+
+    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
+
+class KeymasterHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static KeymasterHidlEnvironment* Instance() {
+        static KeymasterHidlEnvironment* instance = new KeymasterHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override { registerTestService<IKeymasterDevice>(); }
+
+   private:
+    KeymasterHidlEnvironment(){};
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(KeymasterHidlEnvironment);
+};
+
+class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    void TearDown() override {
+        if (key_blob_.size()) {
+            CheckedDeleteKey();
+        }
+        AbortIfNeeded();
+    }
+
+    // SetUpTestCase runs only once per test case, not once per test.
+    static void SetUpTestCase();
+    static void TearDownTestCase() {
+        keymaster_.clear();
+        all_keymasters_.clear();
+    }
+
+    static IKeymasterDevice& keymaster() { return *keymaster_; }
+    static const std::vector<sp<IKeymasterDevice>>& all_keymasters() { return all_keymasters_; }
+    static uint32_t os_version() { return os_version_; }
+    static uint32_t os_patch_level() { return os_patch_level_; }
+
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
+                          KeyCharacteristics* key_characteristics);
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc);
+
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material, HidlBuf* key_blob,
+                        KeyCharacteristics* key_characteristics);
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material);
+
+    ErrorCode ImportWrappedKey(string wrapped_key, string wrapping_key,
+                               const AuthorizationSet& wrapping_key_desc, string masking_key);
+
+    ErrorCode ExportKey(KeyFormat format, const HidlBuf& key_blob, const HidlBuf& client_id,
+                        const HidlBuf& app_data, HidlBuf* key_material);
+    ErrorCode ExportKey(KeyFormat format, HidlBuf* key_material);
+
+    ErrorCode DeleteKey(HidlBuf* key_blob, bool keep_key_blob = false);
+    ErrorCode DeleteKey(bool keep_key_blob = false);
+
+    ErrorCode DeleteAllKeys();
+
+    void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false);
+    void CheckedDeleteKey();
+
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
+                                 const HidlBuf& app_data, KeyCharacteristics* key_characteristics);
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics);
+
+    ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params, OperationHandle* op_handle);
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params);
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params);
+
+    ErrorCode Update(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, AuthorizationSet* out_params, string* output,
+                     size_t* input_consumed);
+    ErrorCode Update(const string& input, string* out, size_t* input_consumed);
+
+    ErrorCode Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, const string& signature, AuthorizationSet* out_params,
+                     string* output);
+    ErrorCode Finish(const string& message, string* output);
+    ErrorCode Finish(const string& message, const string& signature, string* output);
+    ErrorCode Finish(string* output) { return Finish(string(), output); }
+
+    ErrorCode Abort(OperationHandle op_handle);
+
+    void AbortIfNeeded();
+
+    ErrorCode AttestKey(const HidlBuf& key_blob, const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain);
+    ErrorCode AttestKey(const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain);
+
+    string ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params);
+
+    string SignMessage(const HidlBuf& key_blob, const string& message,
+                       const AuthorizationSet& params);
+    string SignMessage(const string& message, const AuthorizationSet& params);
+
+    string MacMessage(const string& message, Digest digest, size_t mac_length);
+
+    void CheckHmacTestVector(const string& key, const string& message, Digest digest,
+                             const string& expected_mac);
+
+    void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
+                               const string& expected_ciphertext);
+
+    void CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
+                                  PaddingMode padding_mode, const string& key, const string& iv,
+                                  const string& input, const string& expected_output);
+
+    void VerifyMessage(const HidlBuf& key_blob, const string& message, const string& signature,
+                       const AuthorizationSet& params);
+    void VerifyMessage(const string& message, const string& signature,
+                       const AuthorizationSet& params);
+
+    string EncryptMessage(const HidlBuf& key_blob, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params);
+    string EncryptMessage(const string& message, const AuthorizationSet& params,
+                          AuthorizationSet* out_params);
+    string EncryptMessage(const string& message, const AuthorizationSet& params);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+                          HidlBuf* iv_out);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+                          const HidlBuf& iv_in);
+
+    string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
+                          const AuthorizationSet& params);
+    string DecryptMessage(const string& ciphertext, const AuthorizationSet& params);
+    string DecryptMessage(const string& ciphertext, BlockMode block_mode, PaddingMode padding_mode,
+                          const HidlBuf& iv);
+
+    std::pair<ErrorCode, HidlBuf> UpgradeKey(const HidlBuf& key_blob);
+
+    static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
+
+    HidlBuf key_blob_;
+    KeyCharacteristics key_characteristics_;
+    OperationHandle op_handle_ = kOpHandleSentinel;
+
+   private:
+    static sp<IKeymasterDevice> keymaster_;
+    static std::vector<sp<IKeymasterDevice>> all_keymasters_;
+    static uint32_t os_version_;
+    static uint32_t os_patch_level_;
+
+    static SecurityLevel securityLevel_;
+    static hidl_string name_;
+    static hidl_string author_;
+};
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_KEYMASTER_HIDL_TEST_H_
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 04b5829..cb6ade2 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -22,21 +22,13 @@
 #include <openssl/evp.h>
 #include <openssl/x509.h>
 
-#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
-#include <android/hardware/keymaster/4.0/types.h>
 #include <cutils/properties.h>
-#include <keymaster/keymaster_configuration.h>
-
-#include <VtsHalHidlTargetTestBase.h>
 
 #include <keymasterV4_0/attestation_record.h>
-#include <keymasterV4_0/authorization_set.h>
 #include <keymasterV4_0/key_param_output.h>
 #include <keymasterV4_0/openssl_utils.h>
 
-using ::android::sp;
-
-using ::std::string;
+#include "KeymasterHidlTest.h"
 
 static bool arm_deleteAllKeys = false;
 static bool dump_Attestations = false;
@@ -165,16 +157,6 @@
     return a_sw == b_sw && a_tee == b_tee;
 }
 
-::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
-    if (set.size() == 0)
-        os << "(Empty)" << ::std::endl;
-    else {
-        os << "\n";
-        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
-    }
-    return os;
-}
-
 namespace test {
 namespace {
 
@@ -370,589 +352,8 @@
     return make_string(a, N);
 }
 
-class HidlBuf : public hidl_vec<uint8_t> {
-    typedef hidl_vec<uint8_t> super;
-
-   public:
-    HidlBuf() {}
-    HidlBuf(const super& other) : super(other) {}
-    HidlBuf(super&& other) : super(std::move(other)) {}
-    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
-
-    HidlBuf& operator=(const super& other) {
-        super::operator=(other);
-        return *this;
-    }
-
-    HidlBuf& operator=(super&& other) {
-        super::operator=(std::move(other));
-        return *this;
-    }
-
-    HidlBuf& operator=(const string& other) {
-        resize(other.size());
-        for (size_t i = 0; i < other.size(); ++i) {
-            (*this)[i] = static_cast<uint8_t>(other[i]);
-        }
-        return *this;
-    }
-
-    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
-};
-
-constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
-
 }  // namespace
 
-class KeymasterHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static KeymasterHidlEnvironment* Instance() {
-        static KeymasterHidlEnvironment* instance = new KeymasterHidlEnvironment;
-        return instance;
-    }
-
-    void registerTestServices() override { registerTestService<IKeymasterDevice>(); }
-
-   private:
-    KeymasterHidlEnvironment(){};
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(KeymasterHidlEnvironment);
-};
-
-class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    void TearDown() override {
-        if (key_blob_.size()) {
-            CheckedDeleteKey();
-        }
-        AbortIfNeeded();
-    }
-
-    // SetUpTestCase runs only once per test case, not once per test.
-    static void SetUpTestCase() {
-        string service_name =
-            KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
-        keymaster_ =
-            ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
-        ASSERT_NE(keymaster_, nullptr);
-
-        ASSERT_TRUE(keymaster_
-                        ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
-                                              const hidl_string& author) {
-                            securityLevel_ = securityLevel;
-                            name_ = name;
-                            author_ = author;
-                        })
-                        .isOk());
-
-        os_version_ = ::keymaster::GetOsVersion();
-        os_patch_level_ = ::keymaster::GetOsPatchlevel();
-    }
-
-    static void TearDownTestCase() { keymaster_.clear(); }
-
-    static IKeymasterDevice& keymaster() { return *keymaster_; }
-    static uint32_t os_version() { return os_version_; }
-    static uint32_t os_patch_level() { return os_patch_level_; }
-
-    ErrorCode GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
-                          KeyCharacteristics* key_characteristics) {
-        EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
-        EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key.  Test bug.";
-        EXPECT_NE(key_characteristics, nullptr)
-            << "Previous characteristics not deleted before generating key.  Test bug.";
-
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->generateKey(key_desc.hidl_data(),
-                                      [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
-                                          const KeyCharacteristics& hidl_key_characteristics) {
-                                          error = hidl_error;
-                                          *key_blob = hidl_key_blob;
-                                          *key_characteristics = hidl_key_characteristics;
-                                      })
-                        .isOk());
-        // On error, blob & characteristics should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_blob->size());
-            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
-                           key_characteristics->hardwareEnforced.size()));
-        }
-        return error;
-    }
-
-    ErrorCode GenerateKey(const AuthorizationSet& key_desc) {
-        return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
-    }
-
-    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
-                        const string& key_material, HidlBuf* key_blob,
-                        KeyCharacteristics* key_characteristics) {
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
-                                    [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
-                                        const KeyCharacteristics& hidl_key_characteristics) {
-                                        error = hidl_error;
-                                        *key_blob = hidl_key_blob;
-                                        *key_characteristics = hidl_key_characteristics;
-                                    })
-                        .isOk());
-        // On error, blob & characteristics should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_blob->size());
-            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
-                           key_characteristics->hardwareEnforced.size()));
-        }
-        return error;
-    }
-
-    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
-                        const string& key_material) {
-        return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
-    }
-
-    ErrorCode ExportKey(KeyFormat format, const HidlBuf& key_blob, const HidlBuf& client_id,
-                        const HidlBuf& app_data, HidlBuf* key_material) {
-        ErrorCode error;
-        EXPECT_TRUE(
-            keymaster_
-                ->exportKey(format, key_blob, client_id, app_data,
-                            [&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
-                                error = hidl_error_code;
-                                *key_material = hidl_key_material;
-                            })
-                .isOk());
-        // On error, blob should be empty.
-        if (error != ErrorCode::OK) {
-            EXPECT_EQ(0U, key_material->size());
-        }
-        return error;
-    }
-
-    ErrorCode ExportKey(KeyFormat format, HidlBuf* key_material) {
-        HidlBuf client_id, app_data;
-        return ExportKey(format, key_blob_, client_id, app_data, key_material);
-    }
-
-    ErrorCode DeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
-        auto rc = keymaster_->deleteKey(*key_blob);
-        if (!keep_key_blob) *key_blob = HidlBuf();
-        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
-        return rc;
-    }
-
-    ErrorCode DeleteKey(bool keep_key_blob = false) { return DeleteKey(&key_blob_, keep_key_blob); }
-
-    ErrorCode DeleteAllKeys() {
-        ErrorCode error = keymaster_->deleteAllKeys();
-        return error;
-    }
-
-    void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
-        auto rc = DeleteKey(key_blob, keep_key_blob);
-        EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
-    }
-
-    void CheckedDeleteKey() { CheckedDeleteKey(&key_blob_); }
-
-    ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
-                                 const HidlBuf& app_data, KeyCharacteristics* key_characteristics) {
-        ErrorCode error = ErrorCode::UNKNOWN_ERROR;
-        EXPECT_TRUE(
-            keymaster_
-                ->getKeyCharacteristics(
-                    key_blob, client_id, app_data,
-                    [&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
-                        error = hidl_error, *key_characteristics = hidl_key_characteristics;
-                    })
-                .isOk());
-        return error;
-    }
-
-    ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics) {
-        HidlBuf client_id, app_data;
-        return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
-                    AuthorizationSet* out_params, OperationHandle* op_handle) {
-        SCOPED_TRACE("Begin");
-        ErrorCode error;
-        OperationHandle saved_handle = *op_handle;
-        EXPECT_TRUE(
-            keymaster_
-                ->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
-                        [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
-                            uint64_t hidl_op_handle) {
-                            error = hidl_error;
-                            *out_params = hidl_out_params;
-                            *op_handle = hidl_op_handle;
-                        })
-                .isOk());
-        if (error != ErrorCode::OK) {
-            // Some implementations may modify *op_handle on error.
-            *op_handle = saved_handle;
-        }
-        return error;
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
-                    AuthorizationSet* out_params) {
-        SCOPED_TRACE("Begin");
-        EXPECT_EQ(kOpHandleSentinel, op_handle_);
-        return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
-    }
-
-    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
-        SCOPED_TRACE("Begin");
-        AuthorizationSet out_params;
-        ErrorCode error = Begin(purpose, in_params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return error;
-    }
-
-    ErrorCode Update(OperationHandle op_handle, const AuthorizationSet& in_params,
-                     const string& input, AuthorizationSet* out_params, string* output,
-                     size_t* input_consumed) {
-        SCOPED_TRACE("Update");
-        ErrorCode error;
-        EXPECT_TRUE(keymaster_
-                        ->update(op_handle, in_params.hidl_data(), HidlBuf(input),
-                                 HardwareAuthToken(), VerificationToken(),
-                                 [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
-                                     const hidl_vec<KeyParameter>& hidl_out_params,
-                                     const HidlBuf& hidl_output) {
-                                     error = hidl_error;
-                                     out_params->push_back(AuthorizationSet(hidl_out_params));
-                                     output->append(hidl_output.to_string());
-                                     *input_consumed = hidl_input_consumed;
-                                 })
-                        .isOk());
-        return error;
-    }
-
-    ErrorCode Update(const string& input, string* out, size_t* input_consumed) {
-        SCOPED_TRACE("Update");
-        AuthorizationSet out_params;
-        ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
-                                 out, input_consumed);
-        EXPECT_TRUE(out_params.empty());
-        return error;
-    }
-
-    ErrorCode Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
-                     const string& input, const string& signature, AuthorizationSet* out_params,
-                     string* output) {
-        SCOPED_TRACE("Finish");
-        ErrorCode error;
-        EXPECT_TRUE(
-            keymaster_
-                ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
-                         HardwareAuthToken(), VerificationToken(),
-                         [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
-                             const HidlBuf& hidl_output) {
-                             error = hidl_error;
-                             *out_params = hidl_out_params;
-                             output->append(hidl_output.to_string());
-                         })
-                .isOk());
-        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
-        return error;
-    }
-
-    ErrorCode Finish(const string& message, string* output) {
-        SCOPED_TRACE("Finish");
-        AuthorizationSet out_params;
-        string finish_output;
-        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
-                                 "" /* signature */, &out_params, output);
-        if (error != ErrorCode::OK) {
-            return error;
-        }
-        EXPECT_EQ(0U, out_params.size());
-        return error;
-    }
-
-    ErrorCode Finish(string* output) { return Finish(string(), output); }
-
-    ErrorCode Finish(const string& message, const string& signature, string* output) {
-        SCOPED_TRACE("Finish");
-        AuthorizationSet out_params;
-        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
-                                 &out_params, output);
-        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
-        if (error != ErrorCode::OK) {
-            return error;
-        }
-        EXPECT_EQ(0U, out_params.size());
-        return error;
-    }
-
-    ErrorCode Abort(OperationHandle op_handle) {
-        SCOPED_TRACE("Abort");
-        auto retval = keymaster_->abort(op_handle);
-        EXPECT_TRUE(retval.isOk());
-        return retval;
-    }
-
-    void AbortIfNeeded() {
-        SCOPED_TRACE("AbortIfNeeded");
-        if (op_handle_ != kOpHandleSentinel) {
-            EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
-            op_handle_ = kOpHandleSentinel;
-        }
-    }
-
-    ErrorCode AttestKey(const HidlBuf& key_blob, const AuthorizationSet& attest_params,
-                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
-        SCOPED_TRACE("AttestKey");
-        ErrorCode error;
-        auto rc = keymaster_->attestKey(
-            key_blob, attest_params.hidl_data(),
-            [&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
-                error = hidl_error;
-                *cert_chain = hidl_cert_chain;
-            });
-
-        EXPECT_TRUE(rc.isOk()) << rc.description();
-        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
-
-        return error;
-    }
-
-    ErrorCode AttestKey(const AuthorizationSet& attest_params,
-                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
-        SCOPED_TRACE("AttestKey");
-        return AttestKey(key_blob_, attest_params, cert_chain);
-    }
-
-    string ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const string& message,
-                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
-        SCOPED_TRACE("ProcessMessage");
-        AuthorizationSet begin_out_params;
-        EXPECT_EQ(ErrorCode::OK,
-                  Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
-
-        string unused;
-        AuthorizationSet finish_params;
-        AuthorizationSet finish_out_params;
-        string output;
-        EXPECT_EQ(ErrorCode::OK,
-                  Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
-        op_handle_ = kOpHandleSentinel;
-
-        out_params->push_back(begin_out_params);
-        out_params->push_back(finish_out_params);
-        return output;
-    }
-
-    string SignMessage(const HidlBuf& key_blob, const string& message,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("SignMessage");
-        AuthorizationSet out_params;
-        string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return signature;
-    }
-
-    string SignMessage(const string& message, const AuthorizationSet& params) {
-        SCOPED_TRACE("SignMessage");
-        return SignMessage(key_blob_, message, params);
-    }
-
-    string MacMessage(const string& message, Digest digest, size_t mac_length) {
-        SCOPED_TRACE("MacMessage");
-        return SignMessage(
-            key_blob_, message,
-            AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
-    }
-
-    void CheckHmacTestVector(const string& key, const string& message, Digest digest,
-                             const string& expected_mac) {
-        SCOPED_TRACE("CheckHmacTestVector");
-        ASSERT_EQ(ErrorCode::OK,
-                  ImportKey(AuthorizationSetBuilder()
-                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                .HmacKey(key.size() * 8)
-                                .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
-                                .Digest(digest),
-                            KeyFormat::RAW, key));
-        string signature = MacMessage(message, digest, expected_mac.size() * 8);
-        EXPECT_EQ(expected_mac, signature)
-            << "Test vector didn't match for key of size " << key.size() << " message of size "
-            << message.size() << " and digest " << digest;
-        CheckedDeleteKey();
-    }
-
-    void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
-                               const string& expected_ciphertext) {
-        SCOPED_TRACE("CheckAesCtrTestVector");
-        ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
-                                               .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .AesEncryptionKey(key.size() * 8)
-                                               .BlockMode(BlockMode::CTR)
-                                               .Authorization(TAG_CALLER_NONCE)
-                                               .Padding(PaddingMode::NONE),
-                                           KeyFormat::RAW, key));
-
-        auto params = AuthorizationSetBuilder()
-                          .Authorization(TAG_NONCE, nonce.data(), nonce.size())
-                          .BlockMode(BlockMode::CTR)
-                          .Padding(PaddingMode::NONE);
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
-        EXPECT_EQ(expected_ciphertext, ciphertext);
-    }
-
-    void CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
-                                  PaddingMode padding_mode, const string& key, const string& iv,
-                                  const string& input, const string& expected_output) {
-        auto authset = AuthorizationSetBuilder()
-                           .TripleDesEncryptionKey(key.size() * 7)
-                           .BlockMode(block_mode)
-                           .Padding(padding_mode);
-        if (iv.size()) authset.Authorization(TAG_CALLER_NONCE);
-
-        ASSERT_EQ(ErrorCode::OK, ImportKey(authset, KeyFormat::RAW, key));
-
-        auto begin_params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
-        if (iv.size()) begin_params.Authorization(TAG_NONCE, iv.data(), iv.size());
-        AuthorizationSet output_params;
-        string output = ProcessMessage(key_blob_, purpose, input, begin_params, &output_params);
-        EXPECT_EQ(expected_output, output);
-    }
-
-    void VerifyMessage(const HidlBuf& key_blob, const string& message, const string& signature,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("VerifyMessage");
-        AuthorizationSet begin_out_params;
-        ASSERT_EQ(ErrorCode::OK,
-                  Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
-
-        string unused;
-        AuthorizationSet finish_params;
-        AuthorizationSet finish_out_params;
-        string output;
-        EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, signature,
-                                        &finish_out_params, &output));
-        op_handle_ = kOpHandleSentinel;
-        EXPECT_TRUE(output.empty());
-    }
-
-    void VerifyMessage(const string& message, const string& signature,
-                       const AuthorizationSet& params) {
-        SCOPED_TRACE("VerifyMessage");
-        VerifyMessage(key_blob_, message, signature, params);
-    }
-
-    string EncryptMessage(const HidlBuf& key_blob, const string& message,
-                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
-        SCOPED_TRACE("EncryptMessage");
-        return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
-    }
-
-    string EncryptMessage(const string& message, const AuthorizationSet& params,
-                          AuthorizationSet* out_params) {
-        SCOPED_TRACE("EncryptMessage");
-        return EncryptMessage(key_blob_, message, params, out_params);
-    }
-
-    string EncryptMessage(const string& message, const AuthorizationSet& params) {
-        SCOPED_TRACE("EncryptMessage");
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(message, params, &out_params);
-        EXPECT_TRUE(out_params.empty())
-            << "Output params should be empty. Contained: " << out_params;
-        return ciphertext;
-    }
-
-    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding) {
-        SCOPED_TRACE("EncryptMessage");
-        auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(message, params, &out_params);
-        EXPECT_TRUE(out_params.empty())
-            << "Output params should be empty. Contained: " << out_params;
-        return ciphertext;
-    }
-
-    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
-                          HidlBuf* iv) {
-        SCOPED_TRACE("EncryptMessage");
-        auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(message, params, &out_params);
-        EXPECT_EQ(1U, out_params.size());
-        auto ivVal = out_params.GetTagValue(TAG_NONCE);
-        EXPECT_TRUE(ivVal.isOk());
-        *iv = ivVal.value();
-        return ciphertext;
-    }
-
-    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
-                          const HidlBuf& iv) {
-        SCOPED_TRACE("EncryptMessage");
-        auto params = AuthorizationSetBuilder()
-                          .BlockMode(block_mode)
-                          .Padding(padding)
-                          .Authorization(TAG_NONCE, iv);
-        AuthorizationSet out_params;
-        string ciphertext = EncryptMessage(message, params, &out_params);
-        return ciphertext;
-    }
-
-    string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
-                          const AuthorizationSet& params) {
-        SCOPED_TRACE("DecryptMessage");
-        AuthorizationSet out_params;
-        string plaintext =
-            ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
-        EXPECT_TRUE(out_params.empty());
-        return plaintext;
-    }
-
-    string DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
-        SCOPED_TRACE("DecryptMessage");
-        return DecryptMessage(key_blob_, ciphertext, params);
-    }
-
-    string DecryptMessage(const string& ciphertext, BlockMode block_mode, PaddingMode padding_mode,
-                          const HidlBuf& iv) {
-        SCOPED_TRACE("DecryptMessage");
-        auto params = AuthorizationSetBuilder()
-                          .BlockMode(block_mode)
-                          .Padding(padding_mode)
-                          .Authorization(TAG_NONCE, iv);
-        return DecryptMessage(key_blob_, ciphertext, params);
-    }
-
-    std::pair<ErrorCode, HidlBuf> UpgradeKey(const HidlBuf& key_blob) {
-        std::pair<ErrorCode, HidlBuf> retval;
-        keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
-                               [&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
-                                   retval = std::tie(error, upgraded_blob);
-                               });
-        return retval;
-    }
-
-    static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
-
-    HidlBuf key_blob_;
-    KeyCharacteristics key_characteristics_;
-    OperationHandle op_handle_ = kOpHandleSentinel;
-
-   private:
-    static sp<IKeymasterDevice> keymaster_;
-    static uint32_t os_version_;
-    static uint32_t os_patch_level_;
-
-    static SecurityLevel securityLevel_;
-    static hidl_string name_;
-    static hidl_string author_;
-};
-
 bool verify_attestation_record(const string& challenge, const string& app_id,
                                AuthorizationSet expected_sw_enforced,
                                AuthorizationSet expected_tee_enforced,
@@ -1012,13 +413,6 @@
     return true;
 }
 
-sp<IKeymasterDevice> KeymasterHidlTest::keymaster_;
-uint32_t KeymasterHidlTest::os_version_;
-uint32_t KeymasterHidlTest::os_patch_level_;
-SecurityLevel KeymasterHidlTest::securityLevel_;
-hidl_string KeymasterHidlTest::name_;
-hidl_string KeymasterHidlTest::author_;
-
 class NewKeyGenerationTest : public KeymasterHidlTest {
    protected:
     void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
@@ -2487,6 +1881,111 @@
     VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
 }
 
+auto wrapped_key = hex2str(
+    "30820173020100048201006F5C273914D9E7EAB667FE62456A57DE64BED4A57DB3EFBB77E6907C82CC36B0BD12CB8A"
+    "85F3F8BC08A26C58186DB5C35636063388A04AE5579D3BDC057F9BB0EB6FDDA5E836DBB1F18A4546A64BA06E3D0132"
+    "AAA3306676638C786FAF0722E6E4145E0C91B009C422691F9F42F9F179DA93E16E7793DE5960E77A387433F0B43E49"
+    "3A7CF77ECA25BA724CC02F916D5792CAA76BC0756D3DB5D110D209B8B30285E9653D91FD89E953F351D82ACE1422CC"
+    "A146F8BD0C2F4CC32D1F81D894F4650043DB46109869696319A1A011BB003F2EBD8FA20B4A43F3226C1F182A39AE81"
+    "A35B9B7590A48B6A6874C9CC0EE0CD9528FB908688B4111932DF478CD7A92B50040CD796B02C370F1FA4CC0124F130"
+    "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420CCD54085"
+    "5F833A5E1480BFD2D36FAF3AEEE15DF5BEABE2691BC82DDE2A7AA91004107CB81BDDCD09E8F4DF575726279F3229");
+
+auto wrapped_key_masked = hex2str(
+    "30820173020100048201009059BB6E48F8036ABE1800D9C74F3DB5F20448F035C2C78AFBCC28AF26581061298CAC78"
+    "A8CA5B79721B60B74490555168488ED696C8930D00463C6FC81BF0B6E4E26C93E018D0E3DC8754C6B261E0A7C3A6DA"
+    "1A223EB59ACA8E13348F14B9E944AF3C224906C1ABFE21ADDEE81FC641D45E092C6B0A75A9BA56C05529AE47ECA0D5"
+    "CD3568501CF04D47391FC695EDE19A3022B347D1BDC6C792A08AA014F87DD4BBD44777B14D7D2273191DDCFE4E8512"
+    "EFA677A14E68E5D820C5513331D687C08B6317FA64D404231D05C74CDD9AEB89D253FBE07154B2080CF4ACA5E1EFCB"
+    "53EB193E8A01DD5F9634B65EF9B49899003E245FDA6A3B137FAC1263E55A6E1D040C6D9721D08589581AB49204A330"
+    "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420A61C6E24"
+    "7E25B3E6E69AA78EB03C2D4AC20D1F99A9A024A76F35C8E2CAB9B68D04101FF7A0E793B9EE4AECEBB9AC4C545254");
+
+auto wrapping_key = hex2str(
+    "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d8900ce56"
+    "b0067f7d70e1fc653f3f34d194c1fed50018fb43db937b06e673a837313d56b1c725150a3fef86acbddc41bb759c28"
+    "54eae32d35841efb5c18d82bc90a1cb5c1d55adf245b02911f0b7cda88c421ff0ebafe7c0d23be312d7bd5921ffaea"
+    "1347c157406fef718f682643e4e5d33c6703d61c0cf7ac0bf4645c11f5c1374c3886427411c449796792e0bef75dec"
+    "858a2123c36753e02a95a96d7c454b504de385a642e0dfc3e60ac3a7ee4991d0d48b0172a95f9536f02ba13cecccb9"
+    "2b727db5c27e5b2f5cec09600b286af5cf14c42024c61ddfe71c2a8d7458f185234cb00e01d282f10f8fc6721d2aed"
+    "3f4833cca2bd8fa62821dd55020301000102820100431447b6251908112b1ee76f99f3711a52b6630960046c2de70d"
+    "e188d833f8b8b91e4d785caeeeaf4f0f74414e2cda40641f7fe24f14c67a88959bdb27766df9e710b630a03adc683b"
+    "5d2c43080e52bee71e9eaeb6de297a5fea1072070d181c822bccff087d63c940ba8a45f670feb29fb4484d1c95e6d2"
+    "579ba02aae0a00900c3ebf490e3d2cd7ee8d0e20c536e4dc5a5097272888cddd7e91f228b1c4d7474c55b8fcd618c4"
+    "a957bbddd5ad7407cc312d8d98a5caf7e08f4a0d6b45bb41c652659d5a5ba05b663737a8696281865ba20fbdd7f851"
+    "e6c56e8cbe0ddbbf24dc03b2d2cb4c3d540fb0af52e034a2d06698b128e5f101e3b51a34f8d8b4f8618102818100de"
+    "392e18d682c829266cc3454e1d6166242f32d9a1d10577753e904ea7d08bff841be5bac82a164c5970007047b8c517"
+    "db8f8f84e37bd5988561bdf503d4dc2bdb38f885434ae42c355f725c9a60f91f0788e1f1a97223b524b5357fdf72e2"
+    "f696bab7d78e32bf92ba8e1864eab1229e91346130748a6e3c124f9149d71c743502818100c95387c0f9d35f137b57"
+    "d0d65c397c5e21cc251e47008ed62a542409c8b6b6ac7f8967b3863ca645fcce49582a9aa17349db6c4a95affdae0d"
+    "ae612e1afac99ed39a2d934c880440aed8832f9843163a47f27f392199dc1202f9a0f9bd08308007cb1e4e7f583093"
+    "66a7de25f7c3c9b880677c068e1be936e81288815252a8a102818057ff8ca1895080b2cae486ef0adfd791fb0235c0"
+    "b8b36cd6c136e52e4085f4ea5a063212a4f105a3764743e53281988aba073f6e0027298e1c4378556e0efca0e14ece"
+    "1af76ad0b030f27af6f0ab35fb73a060d8b1a0e142fa2647e93b32e36d8282ae0a4de50ab7afe85500a16f43a64719"
+    "d6e2b9439823719cd08bcd03178102818100ba73b0bb28e3f81e9bd1c568713b101241acc607976c4ddccc90e65b65"
+    "56ca31516058f92b6e09f3b160ff0e374ec40d78ae4d4979fde6ac06a1a400c61dd31254186af30b22c10582a8a43e"
+    "34fe949c5f3b9755bae7baa7b7b7a6bd03b38cef55c86885fc6c1978b9cee7ef33da507c9df6b9277cff1e6aaa5d57"
+    "aca528466102818100c931617c77829dfb1270502be9195c8f2830885f57dba869536811e6864236d0c4736a0008a1"
+    "45af36b8357a7c3d139966d04c4e00934ea1aede3bb6b8ec841dc95e3f579751e2bfdfe27ae778983f959356210723"
+    "287b0affcc9f727044d48c373f1babde0724fa17a4fd4da0902c7c9b9bf27ba61be6ad02dfddda8f4e6822");
+
+string zero_masking_key =
+    hex2str("0000000000000000000000000000000000000000000000000000000000000000");
+string masking_key = hex2str("D796B02C370F1FA4CC0124F14EC8CBEBE987E825246265050F399A51FD477DFC");
+
+class ImportWrappedKeyTest : public KeymasterHidlTest {};
+
+TEST_F(ImportWrappedKeyTest, Success) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(ErrorCode::OK,
+              ImportWrappedKey(wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key));
+
+    string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    string ciphertext = EncryptMessage(message, params);
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+TEST_F(ImportWrappedKeyTest, SuccessMasked) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(ErrorCode::OK,
+              ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, masking_key));
+}
+
+TEST_F(ImportWrappedKeyTest, WrongMask) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP)
+                                 .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
+
+    ASSERT_EQ(
+        ErrorCode::VERIFICATION_FAILED,
+        ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key));
+}
+
+TEST_F(ImportWrappedKeyTest, WrongPurpose) {
+    auto wrapping_key_desc = AuthorizationSetBuilder()
+                                 .RsaEncryptionKey(2048, 65537)
+                                 .Digest(Digest::SHA1)
+                                 .Padding(PaddingMode::RSA_OAEP);
+
+    ASSERT_EQ(
+        ErrorCode::INCOMPATIBLE_PURPOSE,
+        ImportWrappedKey(wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key));
+}
+
 typedef KeymasterHidlTest EncryptionOperationsTest;
 
 /*