[AWARE] Add validity check on PMK/Passphrase lengths
Bug: 62376042
Test: unit tests + inegrated (sl4a) tests
Change-Id: Ib6383a0ba9ef61114eb72b9a04cc683792b8e89d
diff --git a/Android.mk b/Android.mk
index 313f329..8a530eb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -609,6 +609,7 @@
android.hardware.usb-V1.1-java-constants \
android.hardware.vibrator-V1.0-java-constants \
android.hardware.vibrator-V1.1-java-constants \
+ android.hardware.wifi-V1.0-java-constants \
# Loaded with System.loadLibrary by android.view.textclassifier
LOCAL_REQUIRED_MODULES += libtextclassifier
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 8a4ef23..06e3867 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -342,8 +342,8 @@
*/
public NetworkSpecifier createNetworkSpecifierPassphrase(
@Nullable PeerHandle peerHandle, @NonNull String passphrase) {
- if (passphrase == null || passphrase.length() == 0) {
- throw new IllegalArgumentException("Passphrase must not be null or empty");
+ if (!WifiAwareUtils.validatePassphrase(passphrase)) {
+ throw new IllegalArgumentException("Passphrase must meet length requirements");
}
if (mTerminated) {
@@ -405,8 +405,8 @@
@SystemApi
public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
@NonNull byte[] pmk) {
- if (pmk == null || pmk.length == 0) {
- throw new IllegalArgumentException("PMK must not be null or empty");
+ if (!WifiAwareUtils.validatePmk(pmk)) {
+ throw new IllegalArgumentException("PMK must 32 bytes");
}
if (mTerminated) {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 678d2e6..babbed0 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -269,9 +269,10 @@
Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
return null;
}
- if (passphrase == null || passphrase.length() == 0) {
- throw new IllegalArgumentException("Passphrase must not be null or empty");
+ if (!WifiAwareUtils.validatePassphrase(passphrase)) {
+ throw new IllegalArgumentException("Passphrase must meet length requirements");
}
+
return mgr.createNetworkSpecifier(mClientId, role, peer, null, passphrase);
}
@@ -319,8 +320,8 @@
Log.e(TAG, "createNetworkSpecifierPmk: called after termination");
return null;
}
- if (pmk == null || pmk.length == 0) {
- throw new IllegalArgumentException("PMK must not be null or empty");
+ if (!WifiAwareUtils.validatePmk(pmk)) {
+ throw new IllegalArgumentException("PMK must 32 bytes");
}
return mgr.createNetworkSpecifier(mClientId, role, peer, pmk, null);
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareUtils.java b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
index 4083388..fda7a9a 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
@@ -16,6 +16,8 @@
package android.net.wifi.aware;
+import android.hardware.wifi.V1_0.Constants;
+
/**
* Provides utilities for the Wifi Aware manager/service.
*
@@ -51,4 +53,35 @@
++index;
}
}
+
+ /**
+ * Validates that the passphrase is a non-null string of the right size (per the HAL min/max
+ * length parameters).
+ *
+ * @param passphrase Passphrase to test
+ * @return true if passphrase is valid, false if not
+ */
+ public static boolean validatePassphrase(String passphrase) {
+ if (passphrase == null
+ || passphrase.length() < Constants.NanParamSizeLimits.MIN_PASSPHRASE_LENGTH
+ || passphrase.length() > Constants.NanParamSizeLimits.MAX_PASSPHRASE_LENGTH) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates that the PMK is a non-null byte array of the right size (32 bytes per spec).
+ *
+ * @param pmk PMK to test
+ * @return true if PMK is valid, false if not
+ */
+ public static boolean validatePmk(byte[] pmk) {
+ if (pmk == null || pmk.length != 32) {
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 694b911..d9433c5 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -32,6 +32,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
@@ -938,7 +939,7 @@
final int sessionId = 123;
final PeerHandle peerHandle = new PeerHandle(123412);
final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
- final byte[] pmk = "Some arbitrary byte array".getBytes();
+ final byte[] pmk = "01234567890123456789012345678901".getBytes();
final String passphrase = "A really bad password";
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
@@ -1019,7 +1020,7 @@
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
- final byte[] pmk = "Some arbitrary pmk data".getBytes();
+ final byte[] pmk = "01234567890123456789012345678901".getBytes();
final String passphrase = "A really bad password";
ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
@@ -1070,4 +1071,162 @@
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);
}
+
+ /**
+ * Validate that a null PMK triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientNullPmk() throws Exception {
+ executeNetworkSpecifierWithClient(true, null, null);
+ }
+
+ /**
+ * Validate that a non-32-bytes PMK triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientIncorrectLengthPmk() throws Exception {
+ executeNetworkSpecifierWithClient(true, "012".getBytes(), null);
+ }
+
+ /**
+ * Validate that a null Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientNullPassphrase() throws Exception {
+ executeNetworkSpecifierWithClient(false, null, null);
+ }
+
+ /**
+ * Validate that a too short Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientShortPassphrase() throws Exception {
+ executeNetworkSpecifierWithClient(false, null, "012");
+ }
+
+ /**
+ * Validate that a too long Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientLongPassphrase() throws Exception {
+ executeNetworkSpecifierWithClient(false, null,
+ "0123456789012345678901234567890123456789012345678901234567890123456789");
+ }
+
+ private void executeNetworkSpecifierWithClient(boolean doPmk, byte[] pmk, String passphrase)
+ throws Exception {
+ final int clientId = 4565;
+ final int sessionId = 123;
+ final PeerHandle peerHandle = new PeerHandle(123412);
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ final PublishConfig publishConfig = new PublishConfig.Builder().build();
+
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+ ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+ WifiAwareSession session = sessionCaptor.getValue();
+
+ // (2) publish successfully
+ session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
+ sessionProxyCallback.capture());
+ sessionProxyCallback.getValue().onSessionStarted(sessionId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
+
+ // (3) create network specifier
+ if (doPmk) {
+ publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+ } else {
+ publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle, passphrase);
+ }
+ }
+
+ /**
+ * Validate that a null PMK triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectNullPmk() throws Exception {
+ executeNetworkSpecifierDirect(true, null, null);
+ }
+
+ /**
+ * Validate that a non-32-bytes PMK triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectIncorrectLengthPmk() throws Exception {
+ executeNetworkSpecifierDirect(true, "012".getBytes(), null);
+ }
+
+ /**
+ * Validate that a null Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectNullPassphrase() throws Exception {
+ executeNetworkSpecifierDirect(false, null, null);
+ }
+
+ /**
+ * Validate that a too short Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectShortPassphrase() throws Exception {
+ executeNetworkSpecifierDirect(false, null, "012");
+ }
+
+ /**
+ * Validate that a too long Passphrase triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectLongPassphrase() throws Exception {
+ executeNetworkSpecifierDirect(false, null,
+ "0123456789012345678901234567890123456789012345678901234567890123456789");
+ }
+
+ private void executeNetworkSpecifierDirect(boolean doPmk, byte[] pmk, String passphrase)
+ throws Exception {
+ final int clientId = 134;
+ final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
+ final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
+ final ConfigRequest configRequest = new ConfigRequest.Builder().build();
+
+ ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
+ WifiAwareSession.class);
+ ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
+ .forClass(IWifiAwareEventCallback.class);
+
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
+ mockPublishSession, mockRttListener);
+
+ // (1) connect successfully
+ mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
+ clientProxyCallback.getValue().onConnectSuccess(clientId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
+
+ // (2) create network specifier
+ if (doPmk) {
+ sessionCaptor.getValue().createNetworkSpecifierPmk(role, someMac, pmk);
+ } else {
+ sessionCaptor.getValue().createNetworkSpecifierPassphrase(role, someMac, passphrase);
+ }
+ }
}