[AWARE] Add data-path security configuration (PMK)

Modify the data-path configuration to use the (optional)
PMK to configure security on the data-path.

Remove the old 'token' usage. While that information is
available from the HAL it doesn't provide any security
functionality.

Bug: 33552694
Test: unit tests and integration (sl4a) tests
Change-Id: I0d0aedc7f00405d7325d7af016666c51669653d4
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index 4df9fef..881d0b8 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -65,13 +65,8 @@
  * - capabilities = NET_CAPABILITY_NOT_VPN
  * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
  *   WifiAwareManager.createNetworkSpecifier(...).
- *   The network specifier is encoded as a JSON string with the following key combos:
- *     TYPE_1A: type, role, client_id, session_id, peer_id, token
- *     TYPE_1B: type, role, client_id, session_id, peer_id [only permitted for RESPONDER]
- *     TYPE_2A: type, role, client_id, peer_mac, token
- *     TYPE_2B: type, role, client_id, peer_mac [only permitted for RESPONDER]
- *     TYPE_2C: type, role, client_id, token [only permitted for RESPONDER]
- *     TYPE_2D: type, role, client_id [only permitted for RESPONDER]
+ *   The network specifier is encoded as a JSON string with the key combos described in
+ *   {@link WifiAwareManager} as {@code NETWORK_SPECIFIER_TYPE_*}.
  */
 public class WifiAwareDataPathStateManager {
     private static final String TAG = "WifiAwareDataPathStMgr";
@@ -280,10 +275,9 @@
      *                      related to a discovery session.
      * @param mac           The discovery MAC address of the peer.
      * @param ndpId         The locally assigned ID for the data-path.
-     * @param message       A message sent from the peer as part of the data-path setup process.
      * @return The network specifier of the data-path (or null if none/error)
      */
-    public String onDataPathRequest(int pubSubId, byte[] mac, int ndpId, byte[] message) {
+    public String onDataPathRequest(int pubSubId, byte[] mac, int ndpId) {
         if (VDBG) {
             Log.v(TAG,
                     "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
@@ -298,8 +292,6 @@
              * Checking that the incoming request (from the Initiator) matches the request
              * we (the Responder) already have set up. The rules are:
              * - The discovery session (pub/sub ID) must match.
-             * - The token (if specified - i.e. non-null) must match. A null token == accept any
-             *   Initiator token.
              * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
              *   accept (otherwise matching) requests from any peer MAC.
              */
@@ -307,10 +299,6 @@
                 continue;
             }
 
-            if (entry.getValue().token != null && !Arrays.equals(entry.getValue().token, message)) {
-                continue;
-            }
-
             if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals(
                     entry.getValue().peerDiscoveryMac, mac)) {
                 continue;
@@ -323,18 +311,18 @@
 
         if (nnri == null) {
             Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
-                    + ", mac=" + String.valueOf(HexEncoding.encode(mac)) + ", message=" + message);
+                    + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
             if (DBG) {
                 Log.d(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
             }
-            mMgr.respondToDataPathRequest(false, ndpId, "", "");
+            mMgr.respondToDataPathRequest(false, ndpId, "", null);
             return null;
         }
 
         if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
             Log.w(TAG, "onDataPathRequest: request " + networkSpecifier + " is incorrect state="
                     + nnri.state);
-            mMgr.respondToDataPathRequest(false, ndpId, "", "");
+            mMgr.respondToDataPathRequest(false, ndpId, "", null);
             mNetworkRequestsCache.remove(networkSpecifier);
             return null;
         }
@@ -342,7 +330,7 @@
         nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
         nnri.ndpId = ndpId;
         nnri.interfaceName = selectInterfaceForRequest(nnri);
-        mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, "");
+        mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.pmk);
 
         return networkSpecifier;
     }
@@ -644,7 +632,7 @@
                 nnri.interfaceName = selectInterfaceForRequest(nnri);
                 mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerId,
                         NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP, selectChannelForRequest(nnri),
-                        nnri.peerDiscoveryMac, nnri.interfaceName, nnri.token);
+                        nnri.peerDiscoveryMac, nnri.interfaceName, nnri.pmk);
                 nnri.state =
                         AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
             } else {
@@ -807,7 +795,7 @@
         public int pubSubId = 0;
         public int peerId = 0;
         public byte[] peerDiscoveryMac = null;
-        public byte[] token = null;
+        public byte[] pmk = null;
         public int ndpId;
         public byte[] peerDataMac;
 
@@ -817,7 +805,7 @@
                 WifiAwareStateManager mgr) {
             int type, role, uid, clientId, sessionId = 0, peerId = 0, pubSubId = 0;
             byte[] peerMac = null;
-            byte[] token = null;
+            byte[] pmk = null;
 
             if (VDBG) {
                 Log.v(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier);
@@ -844,10 +832,10 @@
                 }
 
                 if (role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
-                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A) {
+                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
+                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_OOB) {
                     Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
-                            + " -- invalid 'type' value for INITIATOR (only 1A and 2A are "
+                            + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
                             + "permitted)");
                     return null;
                 }
@@ -855,24 +843,20 @@
                 // clientId: always present
                 clientId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID);
 
-                // sessionId: present for types 1A, 1B, 1C, 1D
-                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1D) {
+                // sessionId: present for types IB, IB_ANY_PEER
+                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
+                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
                     sessionId = jsonObject.getInt(
                             WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID);
                 }
 
-                // peer Id: present for types 1A, 1B
-                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B) {
+                // peer Id: present for type IB
+                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB) {
                     peerId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID);
                 }
 
-                // peerMac: present for types 2A, 2B
-                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2B) {
+                // peerMac: present for type OOB
+                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_OOB) {
                     try {
                         peerMac = HexEncoding.decode(jsonObject.getString(
                                 WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
@@ -889,14 +873,12 @@
                     }
                 }
 
-                // token: present for types 1A, 1C, 2A, 2C
-                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2C) {
-                    token = Base64.decode(
-                            jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN),
-                            Base64.DEFAULT);
+                // pmk: always present (though can be an empty array - equivalent to null)
+                pmk = Base64.decode(
+                        jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK),
+                        Base64.DEFAULT);
+                if (pmk != null && pmk.length == 0) {
+                    pmk = null;
                 }
             } catch (JSONException e) {
                 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
@@ -914,10 +896,8 @@
             uid = client.getUid();
 
             // validate the role (if session ID provided: i.e. session 1xx)
-            if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                    || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B
-                    || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C
-                    || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1D) {
+            if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
+                    || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
                 WifiAwareDiscoverySessionState session = client.getSession(sessionId);
                 if (session == null) {
                     Log.e(TAG,
@@ -935,8 +915,7 @@
                     return null;
                 }
 
-                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A
-                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B) {
+                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB) {
                     pubSubId = session.getPubSubId();
                     String peerMacStr = session.getMac(peerId, null);
                     if (peerMacStr == null) {
@@ -971,7 +950,7 @@
             nnri.pubSubId = pubSubId;
             nnri.peerId = peerId;
             nnri.peerDiscoveryMac = peerMac;
-            nnri.token = token;
+            nnri.pmk = pmk;
 
             return nnri;
         }
@@ -984,8 +963,7 @@
                     ", pubSubId=").append(pubSubId).append(", peerDiscoveryMac=").append(
                     peerDiscoveryMac == null ? ""
                             : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(
-                    ", token=").append(token).append(", ndpId=").append(ndpId).append(
-                    ", peerDataMac=").append(
+                    ", ndpId=").append(ndpId).append(", peerDataMac=").append(
                     peerDataMac == null ? "" : String.valueOf(HexEncoding.encode(peerDataMac)));
             return sb.toString();
         }
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
index dbd02cf..a3953cd 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
@@ -19,6 +19,7 @@
 import android.hardware.wifi.V1_0.IWifiNanIface;
 import android.hardware.wifi.V1_0.NanBandIndex;
 import android.hardware.wifi.V1_0.NanBandSpecificConfig;
+import android.hardware.wifi.V1_0.NanCipherSuiteType;
 import android.hardware.wifi.V1_0.NanConfigRequest;
 import android.hardware.wifi.V1_0.NanEnableRequest;
 import android.hardware.wifi.V1_0.NanInitiateDataPathRequest;
@@ -595,11 +596,12 @@
      * @param channel            The channel on which to set up the data-path.
      * @param peer               The MAC address of the peer to create a connection with.
      * @param interfaceName      The interface on which to create the data connection.
-     * @param message An arbitrary byte array to forward to the peer as part of the data path
-     *                request.
+     * @param pmk Pairwise master key (PMK, see IEEE 802.11i). Null value means an unsecured (open)
+     *            datapath.
+     * @param capabilities The capabilities of the firmware.
      */
     public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType,
-            int channel, byte[] peer, String interfaceName, byte[] message) {
+            int channel, byte[] peer, String interfaceName, byte[] pmk, Capabilities capabilities) {
         if (VDBG) {
             Log.v(TAG, "initiateDataPath: transactionId=" + transactionId + ", peerId=" + peerId
                     + ", channelRequestType=" + channelRequestType + ", channel=" + channel
@@ -613,14 +615,24 @@
             return false;
         }
 
+        if (capabilities == null) {
+            Log.e(TAG, "initiateDataPath: null capabilities");
+            return false;
+        }
+
         NanInitiateDataPathRequest req = new NanInitiateDataPathRequest();
         req.peerId = peerId;
         copyArray(peer, req.peerDiscMacAddr);
         req.channelRequestType = channelRequestType;
         req.channel = channel;
         req.ifaceName = interfaceName;
-        req.securityRequired = false;
-        convertLcByteToUcByteArray(message, req.appInfo);
+        if (pmk == null || pmk.length == 0) {
+            req.securityRequired = false;
+        } else {
+            req.securityRequired = true;
+            req.cipherType = getStrongestCipherSuiteType(capabilities.supportedCipherSuites);
+            convertLcByteToUcByteArray(pmk, req.pmk);
+        }
 
         try {
             WifiStatus status = iface.initiateDataPathRequest(transactionId, req);
@@ -645,10 +657,12 @@
      * @param ndpId The NDP (Aware data path) ID. Obtained from the request callback.
      * @param interfaceName The interface on which the data path will be setup. Obtained from the
      *                      request callback.
-     * @param message An arbitrary byte array to forward to the peer in the respond message.
+     * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. A null indicates
+     *            an unsecure (open) link.
+     * @param capabilities The capabilities of the firmware.
      */
     public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId,
-            String interfaceName, byte[] message) {
+            String interfaceName, byte[] pmk, Capabilities capabilities) {
         if (VDBG) {
             Log.v(TAG, "respondToDataPathRequest: transactionId=" + transactionId + ", accept="
                     + accept + ", int ndpId=" + ndpId + ", interfaceName=" + interfaceName);
@@ -660,12 +674,22 @@
             return false;
         }
 
+        if (capabilities == null) {
+            Log.e(TAG, "initiateDataPath: null capabilities");
+            return false;
+        }
+
         NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest();
         req.acceptRequest = accept;
         req.ndpInstanceId = ndpId;
         req.ifaceName = interfaceName;
-        req.securityRequired = false;
-        convertLcByteToUcByteArray(message, req.appInfo);
+        if (pmk == null || pmk.length == 0) {
+            req.securityRequired = false;
+        } else {
+            req.securityRequired = true;
+            req.cipherType = getStrongestCipherSuiteType(capabilities.supportedCipherSuites);
+            convertLcByteToUcByteArray(pmk, req.pmk);
+        }
 
         try {
             WifiStatus status = iface.respondToDataPathIndicationRequest(transactionId, req);
@@ -717,6 +741,21 @@
     // utilities
 
     /**
+     * Returns the strongest supported cipher suite.
+     *
+     * Baseline is very simple: 256 > 128 > 0.
+     */
+    private int getStrongestCipherSuiteType(int supportedCipherSuites) {
+        if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) {
+            return NanCipherSuiteType.SHARED_KEY_256_MASK;
+        }
+        if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) {
+            return NanCipherSuiteType.SHARED_KEY_128_MASK;
+        }
+        return NanCipherSuiteType.NONE;
+    }
+
+    /**
      * Converts a byte[] to an ArrayList<Byte>. Fills in the entries of the 'to' array if
      * provided (non-null), otherwise creates and returns a new ArrayList<>.
      *
@@ -760,7 +799,6 @@
         return sb.toString();
     }
 
-
     /**
      * Dump the internal state of the class.
      */
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
index 3ce8303..892463a 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
@@ -356,8 +356,7 @@
         }
 
         mWifiAwareStateManager.onDataPathRequestNotification(event.discoverySessionId,
-                event.peerDiscMacAddr, event.ndpInstanceId,
-                convertUcByteToLcByteArray(event.appInfo));
+                event.peerDiscMacAddr, event.ndpInstanceId);
     }
 
     @Override
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 898e38b..542b664 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -168,6 +168,7 @@
     private static final String MESSAGE_BUNDLE_KEY_SENT_MESSAGE = "send_message";
     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ = "message_arrival_seq";
     private static final String MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE = "notify_identity_chg";
+    private static final String MESSAGE_BUNDLE_KEY_PMK = "pmk";
 
     private WifiAwareNativeApi mWifiAwareNativeApi;
 
@@ -464,7 +465,7 @@
      * Command to initiate a data-path (executed by the initiator).
      */
     public void initiateDataPathSetup(String networkSpecifier, int peerId, int channelRequestType,
-            int channel, byte[] peer, String interfaceName, byte[] token) {
+            int channel, byte[] peer, String interfaceName, byte[] pmk) {
         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
         msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP;
         msg.obj = networkSpecifier;
@@ -473,7 +474,7 @@
         msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL, channel);
         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peer);
         msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName);
-        msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, token);
+        msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk);
         mSm.sendMessage(msg);
     }
 
@@ -481,13 +482,13 @@
      * Command to respond to the data-path request (executed by the responder).
      */
     public void respondToDataPathRequest(boolean accept, int ndpId, String interfaceName,
-            String token) {
+            byte[] pmk) {
         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
         msg.arg1 = COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST;
         msg.arg2 = ndpId;
         msg.obj = accept;
         msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName);
-        msg.getData().putString(MESSAGE_BUNDLE_KEY_MESSAGE, token);
+        msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk);
         mSm.sendMessage(msg);
     }
 
@@ -657,7 +658,7 @@
     }
 
     /**
-     * Response from firmware to {@link #respondToDataPathRequest(boolean, int, String, String)}.
+     * Response from firmware to {@link #respondToDataPathRequest(boolean, int, String, byte[])}.
      */
     public void onRespondToDataPathSetupRequestResponse(short transactionId, boolean success,
             int reasonOnFailure) {
@@ -789,13 +790,12 @@
     /**
      * Place a callback request on the state machine queue: data-path request (from peer) received.
      */
-    public void onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId, byte[] message) {
+    public void onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId) {
         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
         msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST;
         msg.arg2 = pubSubId;
         msg.obj = ndpId;
         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac);
-        msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message);
         mSm.sendMessage(msg);
     }
 
@@ -1125,8 +1125,7 @@
                 case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST: {
                     String networkSpecifier = mDataPathMgr.onDataPathRequest(msg.arg2,
                             msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS),
-                            (int) msg.obj,
-                            msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA));
+                            (int) msg.obj);
 
                     if (networkSpecifier != null) {
                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
@@ -1368,11 +1367,11 @@
                     int channel = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL);
                     byte[] peer = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
                     String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME);
-                    byte[] token = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE);
+                    byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK);
 
                     waitForResponse = initiateDataPathSetupLocal(mCurrentTransactionId,
                             networkSpecifier, peerId, channelRequestType, channel, peer,
-                            interfaceName, token);
+                            interfaceName, pmk);
 
                     if (waitForResponse) {
                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
@@ -1390,10 +1389,10 @@
                     int ndpId = msg.arg2;
                     boolean accept = (boolean) msg.obj;
                     String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME);
-                    String token = data.getString(MESSAGE_BUNDLE_KEY_MESSAGE);
+                    byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK);
 
                     waitForResponse = respondToDataPathRequestLocal(mCurrentTransactionId, accept,
-                            ndpId, interfaceName, token);
+                            ndpId, interfaceName, pmk);
 
                     break;
                 }
@@ -2065,18 +2064,18 @@
 
     private boolean initiateDataPathSetupLocal(short transactionId, String networkSpecifier,
             int peerId, int channelRequestType, int channel, byte[] peer, String interfaceName,
-            byte[] token) {
+            byte[] pmk) {
         if (VDBG) {
             Log.v(TAG,
                     "initiateDataPathSetupLocal(): transactionId=" + transactionId
                             + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId
                             + ", channelRequestType=" + channelRequestType + ", channel=" + channel
                             + ", peer=" + String.valueOf(HexEncoding.encode(peer))
-                            + ", interfaceName=" + interfaceName + ", token=" + token);
+                            + ", interfaceName=" + interfaceName + ", pmk=" + pmk);
         }
 
         boolean success = mWifiAwareNativeApi.initiateDataPath(transactionId, peerId,
-                channelRequestType, channel, peer, interfaceName, token);
+                channelRequestType, channel, peer, interfaceName, pmk, mCapabilities);
         if (!success) {
             mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusType.INTERNAL_FAILURE);
         }
@@ -2085,18 +2084,16 @@
     }
 
     private boolean respondToDataPathRequestLocal(short transactionId, boolean accept,
-            int ndpId, String interfaceName, String token) {
+            int ndpId, String interfaceName, byte[] pmk) {
         if (VDBG) {
             Log.v(TAG,
                     "respondToDataPathRequestLocal(): transactionId=" + transactionId + ", accept="
                             + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName
-                            + ", token=" + token);
+                            + ", pmk=" + pmk);
         }
 
-        byte[] tokenBytes = token.getBytes();
-
         boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId,
-                interfaceName, tokenBytes);
+                interfaceName, pmk, mCapabilities);
         if (!success) {
             mDataPathMgr.onRespondToDataPathRequest(ndpId, false);
         }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
index 4d88303..6a13576 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -139,9 +139,10 @@
         when(mMockNative.createAwareNetworkInterface(anyShort(), anyString())).thenReturn(true);
         when(mMockNative.deleteAwareNetworkInterface(anyShort(), anyString())).thenReturn(true);
         when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(),
-                any(byte[].class), anyString(), any(byte[].class))).thenReturn(true);
+                any(byte[].class), anyString(), any(byte[].class),
+                any(Capabilities.class))).thenReturn(true);
         when(mMockNative.respondToDataPathRequest(anyShort(), anyBoolean(), anyInt(), anyString(),
-                any(byte[].class))).thenReturn(true);
+                any(byte[].class), any(Capabilities.class))).thenReturn(true);
         when(mMockNative.endDataPath(anyShort(), anyInt())).thenReturn(true);
 
         when(mMockNetworkInterface.configureAgentProperties(
@@ -246,15 +247,6 @@
     }
 
     /**
-     * Validate the fail flow of the Initiator: using session network specifier with a null
-     * token.
-     */
-    @Test(expected = IllegalArgumentException.class)
-    public void testDataPathInitiatorMacNoTokenFail() throws Exception {
-        testDataPathInitiatorUtility(false, true, false, true, false);
-    }
-
-    /**
      * Validate the fail flow of the Initiator: using session network specifier with a 0
      * peer ID.
      */
@@ -273,15 +265,6 @@
     }
 
     /**
-     * Validate the fail flow of the Initiator: using a direct network specifier with a non-null
-     * peer mac and null token.
-     */
-    @Test(expected = IllegalArgumentException.class)
-    public void testDataPathInitiatorDirectMacNoTokenFail() throws Exception {
-        testDataPathInitiatorUtility(true, true, false, true, false);
-    }
-
-    /**
      * Validate the fail flow of the Initiator: using a direct network specifier with a null peer
      * mac and non-null token.
      */
@@ -426,7 +409,7 @@
         final int clientId = 123;
         final int pubSubId = 11234;
         final int ndpId = 2;
-        final String token = "some token";
+        final byte[] pmk = "some bytes".getBytes();
         final PeerHandle peerHandle = new PeerHandle(1341234);
         final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
 
@@ -437,7 +420,7 @@
                 peerDiscoveryMac, inOrder, doPublish);
 
         // (1) request network
-        NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, token,
+        NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, pmk,
                 doPublish);
 
         // corrupt the network specifier: reverse the role (so it's mis-matched)
@@ -458,23 +441,23 @@
         //   Initiator (subscribe): doesn't initiate (i.e. no HAL requests)
         if (doPublish) {
             // (2) get request & respond
-            mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, token.getBytes());
+            mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId);
             mMockLooper.dispatchAll();
             inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false),
-                    eq(ndpId), eq(""), eq(new byte[0]));
+                    eq(ndpId), eq(""), eq(null), any(Capabilities.class));
         }
 
         verifyNoMoreInteractions(mMockNative, mMockCm);
     }
 
     private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac,
-            boolean provideToken, boolean getConfirmation, boolean immediateHalFailure)
+            boolean providePmk, boolean getConfirmation, boolean immediateHalFailure)
             throws Exception {
         final int clientId = 123;
         final int pubSubId = 11234;
         final PeerHandle peerHandle = new PeerHandle(1341234);
         final int ndpId = 2;
-        final String token = "some token";
+        final byte[] pmk = "some bytes".getBytes();
         final String peerToken = "let's go!";
         final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
         final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
@@ -485,7 +468,8 @@
 
         if (immediateHalFailure) {
             when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(),
-                    any(byte[].class), anyString(), any(byte[].class))).thenReturn(false);
+                    any(byte[].class), anyString(), any(byte[].class),
+                    any(Capabilities.class))).thenReturn(false);
 
         }
 
@@ -498,10 +482,10 @@
         if (useDirect) {
             nr = getDirectNetworkRequest(clientId,
                     WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR,
-                    provideMac ? peerDiscoveryMac : null, provideToken ? token : null);
+                    provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null);
         } else {
             nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null,
-                    provideToken ? token : null, false);
+                    providePmk ? pmk : null, false);
         }
 
         Message reqNetworkMsg = Message.obtain();
@@ -513,7 +497,7 @@
         inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(),
                 eq(useDirect ? 0 : peerHandle.peerId),
                 eq(REQUEST_CHANNEL_SETUP), eq(2437), eq(peerDiscoveryMac),
-                eq(sAwareInterfacePrefix + "0"), eq(token.getBytes()));
+                eq(sAwareInterfacePrefix + "0"), eq(pmk), any(Capabilities.class));
         if (immediateHalFailure) {
             // short-circuit the rest of this test
             verifyNoMoreInteractions(mMockNative, mMockCm);
@@ -562,12 +546,12 @@
     }
 
     private void testDataPathResponderUtility(boolean useDirect, boolean provideMac,
-            boolean provideToken, boolean getConfirmation) throws Exception {
+            boolean providePmk, boolean getConfirmation) throws Exception {
         final int clientId = 123;
         final int pubSubId = 11234;
         final PeerHandle peerHandle = new PeerHandle(1341234);
         final int ndpId = 2;
-        final String token = "some token";
+        final byte[] pmk = "some bytes".getBytes();
         final String peerToken = "let's go!";
         final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
         final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
@@ -585,10 +569,10 @@
         if (useDirect) {
             nr = getDirectNetworkRequest(clientId,
                     WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
-                    provideMac ? peerDiscoveryMac : null, provideToken ? token : null);
+                    provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null);
         } else {
             nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null,
-                    provideToken ? token : null, true);
+                    providePmk ? pmk : null, true);
         }
 
         Message reqNetworkMsg = Message.obtain();
@@ -599,10 +583,11 @@
         mMockLooper.dispatchAll();
 
         // (2) get request & respond
-        mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, token.getBytes());
+        mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(true),
-                eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(new byte[0]));
+                eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null),
+                any(Capabilities.class));
         mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0);
         mMockLooper.dispatchAll();
 
@@ -659,7 +644,7 @@
     }
 
     private NetworkRequest getSessionNetworkRequest(int clientId, int sessionId,
-            PeerHandle peerHandle, String token, boolean doPublish)
+            PeerHandle peerHandle, byte[] pmk, boolean doPublish)
             throws Exception {
         final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService);
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
@@ -706,8 +691,12 @@
                     (SubscribeDiscoverySession) discoverySession.capture());
         }
 
-        String ns = discoverySession.getValue().createNetworkSpecifier(peerHandle,
-                (token == null) ? null : token.getBytes());
+        String ns;
+        if (pmk == null) {
+            ns = discoverySession.getValue().createNetworkSpecifierOpen(peerHandle);
+        } else {
+            ns = discoverySession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+        }
 
         NetworkCapabilities nc = new NetworkCapabilities();
         nc.clearAll();
@@ -723,7 +712,7 @@
     }
 
     private NetworkRequest getDirectNetworkRequest(int clientId, int role, byte[] peer,
-            String token) throws Exception {
+            byte[] pmk) throws Exception {
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService);
 
@@ -741,8 +730,12 @@
         mMockLooper.dispatchAll();
         verify(mockCallback).onAttached(sessionCaptor.capture());
 
-        String ns = sessionCaptor.getValue().createNetworkSpecifier(role, peer,
-                (token == null) ? null : token.getBytes());
+        String ns;
+        if (pmk == null) {
+            ns = sessionCaptor.getValue().createNetworkSpecifierOpen(role, peer);
+        } else {
+            ns = sessionCaptor.getValue().createNetworkSpecifierPmk(role, peer, pmk);
+        }
         NetworkCapabilities nc = new NetworkCapabilities();
         nc.clearAll();
         nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);