Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 486a4112 authored by Etan Cohen's avatar Etan Cohen
Browse files

[AWARE] Add validity check on PMK/Passphrase lengths

Bug: 62376042
Test: unit tests + inegrated (sl4a) tests
Change-Id: Ib6383a0ba9ef61114eb72b9a04cc683792b8e89d
parent 2fe945c3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -609,6 +609,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
    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
+4 −4
Original line number Diff line number Diff line
@@ -342,8 +342,8 @@ public class DiscoverySession implements AutoCloseable {
     */
    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 @@ public class DiscoverySession implements AutoCloseable {
    @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) {
+5 −4
Original line number Diff line number Diff line
@@ -269,9 +269,10 @@ public class WifiAwareSession implements AutoCloseable {
            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 @@ public class WifiAwareSession implements AutoCloseable {
            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);
    }
+33 −0
Original line number Diff line number Diff line
@@ -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 @@ public class WifiAwareUtils {
            ++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;
    }
}
+161 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.net.wifi.RttManager;
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 @@ public class WifiAwareManagerTest {
        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 @@ public class WifiAwareManagerTest {
        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 @@ public class WifiAwareManagerTest {
        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);
        }
    }
}