Merge "Fix missing copies of status member variable"
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index 6b8dcdc..ccd1b56 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -26,6 +26,8 @@
         "attestation_record.cpp",
         "authorization_set.cpp",
         "key_param_output.cpp",
+        "keymaster_utils.cpp",
+        "Keymaster.cpp",
         "Keymaster3.cpp",
         "Keymaster4.cpp",
     ],
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
new file mode 100644
index 0000000..bf52c47
--- /dev/null
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -0,0 +1,90 @@
+/*
+ ** Copyright 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.
+ */
+
+#include <keymasterV4_0/Keymaster.h>
+
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <keymasterV4_0/Keymaster3.h>
+#include <keymasterV4_0/Keymaster4.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+using ::android::sp;
+using ::android::hidl::manager::V1_0::IServiceManager;
+
+template <typename Wrapper>
+std::vector<std::unique_ptr<Keymaster>> enumerateDevices(
+    const sp<IServiceManager>& serviceManager) {
+    std::vector<std::unique_ptr<Keymaster>> result;
+
+    bool foundDefault = false;
+    auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor;
+    serviceManager->listByInterface(descriptor, [&](const hidl_vec<hidl_string>& names) {
+        for (auto& name : names) {
+            if (name == "default") foundDefault = true;
+            auto device = Wrapper::WrappedIKeymasterDevice::getService();
+            CHECK(device) << "Failed to get service for " << descriptor << " with interface name "
+                          << name;
+            result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, name)));
+        }
+    });
+
+    if (!foundDefault) {
+        // "default" wasn't provided by listByInterface.  Maybe there's a passthrough
+        // implementation.
+        auto device = Wrapper::WrappedIKeymasterDevice::getService("default");
+        if (device) result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, "default")));
+    }
+
+    return result;
+}
+
+std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() {
+    auto serviceManager = IServiceManager::getService();
+    CHECK(serviceManager) << "Could not retrieve ServiceManager";
+
+    auto km4s = enumerateDevices<Keymaster4>(serviceManager);
+    auto km3s = enumerateDevices<Keymaster3>(serviceManager);
+
+    auto result = std::move(km4s);
+    result.insert(result.end(), std::make_move_iterator(km3s.begin()),
+                  std::make_move_iterator(km3s.end()));
+
+    std::sort(result.begin(), result.end(),
+              [](auto& a, auto& b) { return a->halVersion() > b->halVersion(); });
+
+    size_t i = 1;
+    LOG(INFO) << "List of Keymaster HALs found:";
+    for (auto& hal : result) {
+        auto& version = hal->halVersion();
+        LOG(INFO) << "Keymaster HAL #" << i << ": " << version.keymasterName << " from "
+                  << version.authorName << " SecurityLevel: " << toString(version.securityLevel)
+                  << " HAL : " << hal->descriptor() << " instance " << hal->instanceName();
+    }
+
+    return result;
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+};  // namespace android
diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.0/support/Keymaster3.cpp
index 6dfe85b..b2cdbd9 100644
--- a/keymaster/4.0/support/Keymaster3.cpp
+++ b/keymaster/4.0/support/Keymaster3.cpp
@@ -18,7 +18,7 @@
 #include <keymasterV4_0/Keymaster3.h>
 
 #include <android-base/logging.h>
-#include <hardware/hw_auth_token.h>
+#include <keymasterV4_0/keymaster_utils.h>
 
 namespace android {
 namespace hardware {
@@ -82,35 +82,6 @@
     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);
@@ -139,37 +110,32 @@
         [&](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;
+            version_ = {keymasterName, keymasterAuthorName, 0 /* major version, filled below */,
+                        isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE,
+                        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;
+    if (version_.securityLevel == SecurityLevel::SOFTWARE) {
+        version_.majorVersion = 3;
     } else if (supportsAttestation_) {
-        majorVersion_ = 3;  // Could be 2, doesn't matter.
+        version_.majorVersion = 3;  // Could be 2, doesn't matter.
     } else if (supportsSymmetricCryptography_) {
-        majorVersion_ = 1;
+        version_.majorVersion = 1;
     } else {
-        majorVersion_ = 0;
+        version_.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_);
+    _hidl_cb(version_.securityLevel,
+             std::string(version_.keymasterName) + " (wrapped by keystore::Keymaster3)",
+             version_.authorName);
     return Void();
 }
 
diff --git a/keymaster/4.0/support/Keymaster4.cpp b/keymaster/4.0/support/Keymaster4.cpp
index fdf78ae..cc3d656 100644
--- a/keymaster/4.0/support/Keymaster4.cpp
+++ b/keymaster/4.0/support/Keymaster4.cpp
@@ -28,19 +28,17 @@
 void Keymaster4::getVersionIfNeeded() {
     if (haveVersion_) return;
 
-    auto rc = dev_->getHardwareInfo([&](SecurityLevel securityLevel, auto...) {
-        securityLevel_ = securityLevel;
-        haveVersion_ = true;
-    });
+    auto rc =
+        dev_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& keymasterName,
+                                  const hidl_string& authorName) {
+            version_ = {keymasterName, authorName, 4 /* major version */, securityLevel,
+                        true /* supportsEc */};
+            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
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index 81cf365..bf77420 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -503,6 +503,18 @@
     return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
 }
 
+AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) {
+    return BlockMode(BlockMode::GCM)
+        .Padding(PaddingMode::NONE)
+        .Authorization(TAG_MIN_MAC_LENGTH, minMacLength);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) {
+    return BlockMode(BlockMode::GCM)
+        .Padding(PaddingMode::NONE)
+        .Authorization(TAG_MAC_LENGTH, macLength);
+}
+
 AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode(
     std::initializer_list<V4_0::BlockMode> blockModes) {
     for (auto mode : blockModes) {
@@ -519,6 +531,14 @@
     return *this;
 }
 
+AuthorizationSetBuilder& AuthorizationSetBuilder::Padding(
+    std::initializer_list<V4_0::PaddingMode> paddingModes) {
+    for (auto paddingMode : paddingModes) {
+        push_back(TAG_PADDING, paddingMode);
+    }
+    return *this;
+}
+
 }  // namespace V4_0
 }  // namespace keymaster
 }  // namespace hardware
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
index 2686fcd..f9efd51 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -37,16 +37,37 @@
  */
 class Keymaster : public IKeymasterDevice {
    public:
+    Keymaster(const hidl_string& descriptor, const hidl_string& instanceName)
+        : descriptor_(descriptor), instanceName_(instanceName) {}
     virtual ~Keymaster() {}
 
     struct VersionResult {
-        ErrorCode error;
+        hidl_string keymasterName;
+        hidl_string authorName;
         uint8_t majorVersion;
         SecurityLevel securityLevel;
         bool supportsEc;
+
+        bool operator>(const VersionResult& other) const {
+            auto lhs = std::tie(securityLevel, majorVersion, supportsEc);
+            auto rhs = std::tie(other.securityLevel, other.majorVersion, other.supportsEc);
+            return lhs > rhs;
+        }
     };
 
-    virtual VersionResult halVersion() = 0;
+    virtual const VersionResult& halVersion() = 0;
+    const hidl_string& descriptor() { return descriptor_; }
+    const hidl_string& instanceName() { return instanceName_; }
+
+    /**
+     * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least
+     * secure (as defined by VersionResult::operator<).
+     */
+    static std::vector<std::unique_ptr<Keymaster>> enumerateAvailableDevices();
+
+   private:
+    hidl_string descriptor_;
+    hidl_string instanceName_;
 };
 
 }  // namespace support
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
index 4054620..2bb77ca 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
@@ -40,9 +40,15 @@
 class Keymaster3 : public Keymaster {
    public:
     using WrappedIKeymasterDevice = IKeymaster3Device;
-    Keymaster3(sp<IKeymaster3Device> km3_dev) : km3_dev_(km3_dev), haveVersion_(false) {}
+    Keymaster3(sp<IKeymaster3Device> km3_dev, const hidl_string& instanceName)
+        : Keymaster(IKeymaster3Device::descriptor, instanceName),
+          km3_dev_(km3_dev),
+          haveVersion_(false) {}
 
-    VersionResult halVersion() override;
+    const VersionResult& halVersion() override {
+        getVersionIfNeeded();
+        return version_;
+    }
 
     Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb);
 
@@ -114,14 +120,10 @@
     sp<IKeymaster3Device> km3_dev_;
 
     bool haveVersion_;
-    uint8_t majorVersion_;
-    SecurityLevel securityLevel_;
-    bool supportsEllipticCurve_;
+    VersionResult version_;
     bool supportsSymmetricCryptography_;
     bool supportsAttestation_;
     bool supportsAllDigests_;
-    std::string keymasterName_;
-    std::string authorName_;
 };
 
 }  // namespace support
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
index 86ef4f8..96afb13 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
@@ -32,11 +32,15 @@
 class Keymaster4 : public Keymaster {
    public:
     using WrappedIKeymasterDevice = IKeymaster4Device;
-    Keymaster4(sp<IKeymasterDevice> km4_dev) : haveVersion_(false), dev_(km4_dev) {}
+    Keymaster4(sp<IKeymasterDevice> km4_dev, const hidl_string& instanceName)
+        : Keymaster(IKeymaster4Device::descriptor, instanceName),
+          haveVersion_(false),
+          dev_(km4_dev) {}
 
-    uint8_t halMajorVersion() { return 4; }
-
-    VersionResult halVersion() override;
+    const VersionResult& halVersion() override {
+        getVersionIfNeeded();
+        return version_;
+    }
 
     Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
         return dev_->getHardwareInfo(_hidl_cb);
@@ -143,7 +147,7 @@
     void getVersionIfNeeded();
 
     bool haveVersion_;
-    SecurityLevel securityLevel_;
+    VersionResult version_;
     sp<IKeymaster4Device> dev_;
 };
 
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index 09a06fe..6c7fd35 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -270,11 +270,16 @@
 
     AuthorizationSetBuilder& SigningKey();
     AuthorizationSetBuilder& EncryptionKey();
+
     AuthorizationSetBuilder& NoDigestOrPadding();
+
     AuthorizationSetBuilder& EcbMode();
+    AuthorizationSetBuilder& GcmModeMinMacLen(uint32_t minMacLength);
+    AuthorizationSetBuilder& GcmModeMacLen(uint32_t macLength);
 
     AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes);
     AuthorizationSetBuilder& Digest(std::initializer_list<Digest> digests);
+    AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
 
     template <typename... T>
     AuthorizationSetBuilder& BlockMode(T&&... a) {
@@ -288,10 +293,6 @@
     AuthorizationSetBuilder& Padding(T&&... a) {
         return Padding({std::forward<T>(a)...});
     }
-
-    AuthorizationSetBuilder& Padding(PaddingMode padding) {
-        return Authorization(TAG_PADDING, padding);
-    }
 };
 
 }  // namespace V4_0
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
new file mode 100644
index 0000000..1c1b000
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_UTILS_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_UTILS_H_
+
+#include <android/hardware/keymaster/4.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
+                                             bool inPlace = true) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(data), length, !inPlace);
+    return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value, bool inPlace = true) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(value.data())),
+                         static_cast<size_t>(value.size()), !inPlace);
+    return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob,
+                                             bool inPlace = true) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size()),
+                         !inPlace);
+    return result;
+}
+
+HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer);
+hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token);
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_UTILS_H_
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
new file mode 100644
index 0000000..bc610aa
--- /dev/null
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include <hardware/hw_auth_token.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace support {
+
+template <typename T, typename InIter>
+inline static InIter copy_bytes_from_iterator(T* value, InIter src) {
+    uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value);
+    std::copy(src, src + sizeof(T), value_ptr);
+    return src + sizeof(T);
+}
+
+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;
+
+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;
+}
+
+HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer) {
+    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");
+
+    if (buffer.size() != sizeof(hw_auth_token_t)) return {};
+
+    auto pos = buffer.begin();
+    ++pos;  // skip first byte
+    pos = copy_bytes_from_iterator(&token.challenge, pos);
+    pos = copy_bytes_from_iterator(&token.userId, pos);
+    pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
+    pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
+    token.authenticatorType = static_cast<HardwareAuthenticatorType>(
+        ntohl(static_cast<uint32_t>(token.authenticatorType)));
+    pos = copy_bytes_from_iterator(&token.timestamp, pos);
+    token.timestamp = ntohq(token.timestamp);
+    token.mac.resize(kHmacSize);
+    std::copy(pos, pos + kHmacSize, token.mac.data());
+
+    return token;
+}
+
+}  // namespace support
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index c8c8a32..fafd6ad 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -8,6 +8,7 @@
     },
     srcs: [
         "ISupplicant.hal",
+        "ISupplicantStaNetwork.hal",
     ],
     interfaces: [
         "android.hardware.wifi.supplicant@1.0",
diff --git a/wifi/supplicant/1.1/ISupplicantStaNetwork.hal b/wifi/supplicant/1.1/ISupplicantStaNetwork.hal
new file mode 100644
index 0000000..186fe75
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaNetwork.hal
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016 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.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantNetwork;
+import @1.0::ISupplicantStaNetworkCallback;
+import @1.0::SupplicantStatus;
+import @1.0::ISupplicantStaNetwork;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * configuration it controls.
+ */
+interface ISupplicantStaNetwork extends @1.0::ISupplicantStaNetwork {
+    /**
+     * EAP IMSI Identity to be used for authentication to EAP SIM networks.
+     * The identity must be derived from the IMSI retrieved from the SIM card.
+     *
+     * See RFC4186 & RFC4187 & RFC5448 for EAP SIM protocols.
+     *
+     * Identity string is built from IMSI. Format is:
+     *       eapPrefix | IMSI | '@' | realm
+     * where:
+     * - "|" denotes concatenation
+     * - realm is the 3GPP network domain name derived from the given
+     *   MCC/MNC according to the 3GGP spec(TS23.003)
+     *
+     * eapPrefix value:
+     * '0' - EAP-AKA Identity
+     * '1' - EAP-SIM Identity
+     * '6' - EAP-AKA-PRIME Identity
+     */
+    typedef vec<uint8_t> EapSimIdentity;
+
+    /**
+     * Encrypted EAP IMSI Identity to be used for authentication to EAP SIM
+     * networks which supports encrypted IMSI.
+     * The identity must be derived from the IMSI retrieved from the SIM card.
+     * This identity is then encrypted using the public key of the carrier.
+     *
+     * See RFC4186 & RFC4187 & RFC5448 for EAP SIM protocols.
+     * See section 7.1 of RFC 2437 for RSA-OAEP encryption scheme.
+     *
+     * Identity string is built from encrypted IMSI. Format is:
+     *       '\0' | Base64{RSA-OAEP-SHA-256(eapPrefix | IMSI)}
+     *       | '@' | realm | {',' Key Identifier}
+     * where:
+     * - "|" denotes concatenation
+     * - "{}" denotes an optional value
+     * - realm is the 3GPP network domain name derived from the given
+     *   MCC/MNC according to the 3GGP spec(TS23.003)
+     * - Key Identifier is a null-terminated string of the form "<Key>=<Value>"
+     */
+    typedef vec<uint8_t> EapSimEncryptedIdentity;
+
+    /**
+     * Set EAP encrypted IMSI Identity for this network.
+     *
+     * @param identity Identity string built from the encrypted IMSI.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    setEapEncryptedImsiIdentity(EapSimEncryptedIdentity identity)
+        generates (SupplicantStatus status);
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapIdentityRequest| request.
+     *
+     * @param identity Identity string containing the IMSI.
+     * @param encryptedIdentity Identity string containing the encrypted IMSI.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    sendNetworkEapIdentityResponse_1_1(
+            EapSimIdentity identity,
+            EapSimEncryptedIdentity encryptedIdentity)
+        generates (SupplicantStatus status);
+};