diff options
author | Etan Cohen <etancohen@google.com> | 2017-02-21 10:08:49 -0800 |
---|---|---|
committer | Etan Cohen <etancohen@google.com> | 2017-03-07 19:07:50 -0800 |
commit | 31389a22a6f12b12cca89d53b5f9f80fdcd76385 (patch) | |
tree | 3db6cf4f5871d2a6ae76441f6132d355f7cf8989 | |
parent | 6f8030b6e550cffe6bea94a14c06173aeae0b873 (diff) |
[AWARE] Add data-path security configuration (Passphrase)
Add support for Passphrase-based security.
Bug: 33552694
Test: unit tests and integration (sl4a) tests
Change-Id: Id883367f79ca38501e8670097a31245f048e5d71
4 files changed, 62 insertions, 32 deletions
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java index 851a580a2..5842a3bf8 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java @@ -315,14 +315,14 @@ public class WifiAwareDataPathStateManager { if (DBG) { Log.d(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache); } - mMgr.respondToDataPathRequest(false, ndpId, "", null); + mMgr.respondToDataPathRequest(false, ndpId, "", null, 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, "", null); + mMgr.respondToDataPathRequest(false, ndpId, "", null, null); mNetworkRequestsCache.remove(networkSpecifier); return null; } @@ -330,7 +330,7 @@ public class WifiAwareDataPathStateManager { nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE; nnri.ndpId = ndpId; nnri.interfaceName = selectInterfaceForRequest(nnri); - mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.pmk); + mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.pmk, nnri.passphrase); return networkSpecifier; } @@ -631,7 +631,7 @@ public class WifiAwareDataPathStateManager { nnri.interfaceName = selectInterfaceForRequest(nnri); mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerId, NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP, selectChannelForRequest(nnri), - nnri.peerDiscoveryMac, nnri.interfaceName, nnri.pmk); + nnri.peerDiscoveryMac, nnri.interfaceName, nnri.pmk, nnri.passphrase); nnri.state = AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE; } else { @@ -795,6 +795,7 @@ public class WifiAwareDataPathStateManager { public int peerId = 0; public byte[] peerDiscoveryMac = null; public byte[] pmk = null; + public String passphrase = null; public int ndpId; public byte[] peerDataMac; @@ -805,6 +806,7 @@ public class WifiAwareDataPathStateManager { int type, role, uid, clientId, sessionId = 0, peerId = 0, pubSubId = 0; byte[] peerMac = null; byte[] pmk = null; + String passphrase = null; if (VDBG) { Log.v(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier); @@ -879,6 +881,21 @@ public class WifiAwareDataPathStateManager { if (pmk != null && pmk.length == 0) { pmk = null; } + + // passphrase: always present (though can be an empty string - equivalent to null) + passphrase = jsonObject.getString( + WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE); + if (passphrase != null && passphrase.length() == 0) { + passphrase = null; + } + + if (passphrase != null) { + if (pmk != null) { + Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier + + " -- invalid: can't specify both PMK and Passphrase"); + return null; + } + } } catch (JSONException e) { Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier + " -- invalid JSON format -- e=" + e); @@ -950,6 +967,7 @@ public class WifiAwareDataPathStateManager { nnri.peerId = peerId; nnri.peerDiscoveryMac = peerMac; nnri.pmk = pmk; + nnri.passphrase = passphrase; return nnri; } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java index a3953cd6f..7990db7d1 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java @@ -584,7 +584,8 @@ public class WifiAwareNativeApi { } /** - * Initiates setting up a data-path between device and peer. + * Initiates setting up a data-path between device and peer. Security is provided by either + * PMK or Passphrase - if both are null then an open (unencrypted) link is set up. * * @param transactionId Transaction ID for the transaction - used in the async callback to * match with the original request. @@ -596,12 +597,13 @@ public class WifiAwareNativeApi { * @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 pmk Pairwise master key (PMK, see IEEE 802.11i). Null value means an unsecured (open) - * datapath. + * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. + * @param passphrase Passphrase for the data-path. * @param capabilities The capabilities of the firmware. */ public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, - int channel, byte[] peer, String interfaceName, byte[] pmk, Capabilities capabilities) { + int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase, + Capabilities capabilities) { if (VDBG) { Log.v(TAG, "initiateDataPath: transactionId=" + transactionId + ", peerId=" + peerId + ", channelRequestType=" + channelRequestType + ", channel=" + channel @@ -633,6 +635,7 @@ public class WifiAwareNativeApi { req.cipherType = getStrongestCipherSuiteType(capabilities.supportedCipherSuites); convertLcByteToUcByteArray(pmk, req.pmk); } + // TODO: b/35866810 connect passphrase to HAL! try { WifiStatus status = iface.initiateDataPathRequest(transactionId, req); @@ -649,7 +652,8 @@ public class WifiAwareNativeApi { } /** - * Responds to a data request from a peer. + * Responds to a data request from a peer. Security is provided by either PMK or Passphrase - + * if both are null then an open (unencrypted) link is set up. * * @param transactionId Transaction ID for the transaction - used in the async callback to * match with the original request. @@ -657,12 +661,12 @@ public class WifiAwareNativeApi { * @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 pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. A null indicates - * an unsecure (open) link. + * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. + * @param passphrase Passphrase for the data-path. * @param capabilities The capabilities of the firmware. */ public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, - String interfaceName, byte[] pmk, Capabilities capabilities) { + String interfaceName, byte[] pmk, String passphrase, Capabilities capabilities) { if (VDBG) { Log.v(TAG, "respondToDataPathRequest: transactionId=" + transactionId + ", accept=" + accept + ", int ndpId=" + ndpId + ", interfaceName=" + interfaceName); @@ -690,6 +694,7 @@ public class WifiAwareNativeApi { req.cipherType = getStrongestCipherSuiteType(capabilities.supportedCipherSuites); convertLcByteToUcByteArray(pmk, req.pmk); } + // TODO: b/35866810 connect passphrase to HAL! try { WifiStatus status = iface.respondToDataPathIndicationRequest(transactionId, req); diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java index 542b66455..76bfcea55 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java @@ -169,6 +169,7 @@ public class WifiAwareStateManager { 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 static final String MESSAGE_BUNDLE_KEY_PASSPHRASE = "passphrase"; private WifiAwareNativeApi mWifiAwareNativeApi; @@ -465,7 +466,7 @@ public class WifiAwareStateManager { * 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[] pmk) { + int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP; msg.obj = networkSpecifier; @@ -475,6 +476,7 @@ public class WifiAwareStateManager { msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peer); msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); + msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); mSm.sendMessage(msg); } @@ -482,13 +484,14 @@ public class WifiAwareStateManager { * Command to respond to the data-path request (executed by the responder). */ public void respondToDataPathRequest(boolean accept, int ndpId, String interfaceName, - byte[] pmk) { + byte[] pmk, String passphrase) { 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().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); + msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); mSm.sendMessage(msg); } @@ -634,7 +637,7 @@ public class WifiAwareStateManager { /** * Response from firmware to {@link #initiateDataPathSetup(String, int, int, int, byte[], - * String, byte[])}. Indicates that command has started succesfully (not completed!). + * String, byte[], String)}. Indicates that command has started succesfully (not completed!). */ public void onInitiateDataPathResponseSuccess(short transactionId, int ndpId) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); @@ -646,8 +649,8 @@ public class WifiAwareStateManager { /** * Response from firmware to - * {@link #initiateDataPathSetup(String, int, int, int, byte[], String, byte[])}. Indicates - * that command has failed. + * {@link #initiateDataPathSetup(String, int, int, int, byte[], String, byte[], String)}. + * Indicates that command has failed. */ public void onInitiateDataPathResponseFail(short transactionId, int reason) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); @@ -658,7 +661,8 @@ public class WifiAwareStateManager { } /** - * Response from firmware to {@link #respondToDataPathRequest(boolean, int, String, byte[])}. + * Response from firmware to + * {@link #respondToDataPathRequest(boolean, int, String, byte[], String)}. */ public void onRespondToDataPathSetupRequestResponse(short transactionId, boolean success, int reasonOnFailure) { @@ -1368,10 +1372,11 @@ public class WifiAwareStateManager { byte[] peer = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); + String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); waitForResponse = initiateDataPathSetupLocal(mCurrentTransactionId, networkSpecifier, peerId, channelRequestType, channel, peer, - interfaceName, pmk); + interfaceName, pmk, passphrase); if (waitForResponse) { WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), @@ -1390,9 +1395,10 @@ public class WifiAwareStateManager { boolean accept = (boolean) msg.obj; String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); + String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); waitForResponse = respondToDataPathRequestLocal(mCurrentTransactionId, accept, - ndpId, interfaceName, pmk); + ndpId, interfaceName, pmk, passphrase); break; } @@ -2064,18 +2070,19 @@ public class WifiAwareStateManager { private boolean initiateDataPathSetupLocal(short transactionId, String networkSpecifier, int peerId, int channelRequestType, int channel, byte[] peer, String interfaceName, - byte[] pmk) { + byte[] pmk, String passphrase) { if (VDBG) { Log.v(TAG, "initiateDataPathSetupLocal(): transactionId=" + transactionId + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId + ", channelRequestType=" + channelRequestType + ", channel=" + channel + ", peer=" + String.valueOf(HexEncoding.encode(peer)) - + ", interfaceName=" + interfaceName + ", pmk=" + pmk); + + ", interfaceName=" + interfaceName + ", pmk=" + pmk + + ", passphrase=" + passphrase); } boolean success = mWifiAwareNativeApi.initiateDataPath(transactionId, peerId, - channelRequestType, channel, peer, interfaceName, pmk, mCapabilities); + channelRequestType, channel, peer, interfaceName, pmk, passphrase, mCapabilities); if (!success) { mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusType.INTERNAL_FAILURE); } @@ -2084,16 +2091,16 @@ public class WifiAwareStateManager { } private boolean respondToDataPathRequestLocal(short transactionId, boolean accept, - int ndpId, String interfaceName, byte[] pmk) { + int ndpId, String interfaceName, byte[] pmk, String passphrase) { if (VDBG) { Log.v(TAG, "respondToDataPathRequestLocal(): transactionId=" + transactionId + ", accept=" + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName - + ", pmk=" + pmk); + + ", pmk=" + pmk + ", passphrase=" + passphrase); } boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId, - interfaceName, pmk, mCapabilities); + interfaceName, pmk, passphrase, mCapabilities); if (!success) { mDataPathMgr.onRespondToDataPathRequest(ndpId, false); } diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index 6a13576e6..724a4b053 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -139,10 +139,10 @@ public class WifiAwareDataPathStateManagerTest { 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), + any(byte[].class), anyString(), any(byte[].class), anyString(), any(Capabilities.class))).thenReturn(true); when(mMockNative.respondToDataPathRequest(anyShort(), anyBoolean(), anyInt(), anyString(), - any(byte[].class), any(Capabilities.class))).thenReturn(true); + any(byte[].class), anyString(), any(Capabilities.class))).thenReturn(true); when(mMockNative.endDataPath(anyShort(), anyInt())).thenReturn(true); when(mMockNetworkInterface.configureAgentProperties( @@ -444,7 +444,7 @@ public class WifiAwareDataPathStateManagerTest { mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), - eq(ndpId), eq(""), eq(null), any(Capabilities.class)); + eq(ndpId), eq(""), eq(null), eq(null), any(Capabilities.class)); } verifyNoMoreInteractions(mMockNative, mMockCm); @@ -468,7 +468,7 @@ public class WifiAwareDataPathStateManagerTest { if (immediateHalFailure) { when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), - any(byte[].class), anyString(), any(byte[].class), + any(byte[].class), anyString(), any(byte[].class), anyString(), any(Capabilities.class))).thenReturn(false); } @@ -497,7 +497,7 @@ public class WifiAwareDataPathStateManagerTest { inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(useDirect ? 0 : peerHandle.peerId), eq(REQUEST_CHANNEL_SETUP), eq(2437), eq(peerDiscoveryMac), - eq(sAwareInterfacePrefix + "0"), eq(pmk), any(Capabilities.class)); + eq(sAwareInterfacePrefix + "0"), eq(pmk), eq(null), any(Capabilities.class)); if (immediateHalFailure) { // short-circuit the rest of this test verifyNoMoreInteractions(mMockNative, mMockCm); @@ -586,7 +586,7 @@ public class WifiAwareDataPathStateManagerTest { mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(true), - eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null), + eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null), eq(null), any(Capabilities.class)); mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0); mMockLooper.dispatchAll(); |