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

Commit 83e2e0e8 authored by Raphael Kim's avatar Raphael Kim
Browse files

[CDM] remove platform version exchange protocol

Bug: 280846138
Test: Tested manually from raven (U) -> r11 (T)
Change-Id: I78d4b6cd334963d44e1081f97f190e83da8ea5ee
parent 0bdf223f
Loading
Loading
Loading
Loading
+16 −105
Original line number Diff line number Diff line
@@ -19,10 +19,8 @@ package com.android.server.companion.transport;
import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;

import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PLATFORM_INFO;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManagerInternal;
import android.companion.AssociationInfo;
@@ -33,7 +31,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -46,7 +43,6 @@ import com.android.server.companion.AssociationStore;

import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -58,19 +54,8 @@ public class CompanionTransportManager {
    private static final String TAG = "CDM_CompanionTransportManager";
    private static final boolean DEBUG = false;

    private static final int SECURE_CHANNEL_AVAILABLE_SDK = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
    private static final int NON_ANDROID = -1;

    private boolean mSecureTransportEnabled = true;

    private static boolean isRequest(int message) {
        return (message & 0xFF000000) == 0x63000000;
    }

    private static boolean isResponse(int message) {
        return (message & 0xFF000000) == 0x33000000;
    }

    private final Context mContext;
    private final AssociationStore mAssociationStore;

@@ -84,10 +69,6 @@ public class CompanionTransportManager {
    @NonNull
    private final SparseArray<IOnMessageReceivedListener> mMessageListeners = new SparseArray<>();


    @Nullable
    private Transport mTempTransport;

    public CompanionTransportManager(Context context, AssociationStore associationStore) {
        mContext = context;
        mAssociationStore = associationStore;
@@ -199,7 +180,8 @@ public class CompanionTransportManager {
                detachSystemDataTransport(packageName, userId, associationId);
            }

            initializeTransport(associationId, fd);
            // TODO: Implement new API to pass a PSK
            initializeTransport(associationId, fd, null);

            notifyOnTransportsChanged();
        }
@@ -237,107 +219,36 @@ public class CompanionTransportManager {
        });
    }

    private void initializeTransport(int associationId, ParcelFileDescriptor fd) {
    private void initializeTransport(int associationId,
                                     ParcelFileDescriptor fd,
                                     byte[] preSharedKey) {
        Slog.i(TAG, "Initializing transport");
        Transport transport;
        if (!isSecureTransportEnabled()) {
            Transport transport = new RawTransport(associationId, fd, mContext);
            addMessageListenersToTransport(transport);
            transport.start();
            synchronized (mTransports) {
                mTransports.put(associationId, transport);
            }
            Slog.i(TAG, "RawTransport is created");
            return;
        }

        // Exchange platform info to decide which transport should be created
        mTempTransport = new RawTransport(associationId, fd, mContext);
        addMessageListenersToTransport(mTempTransport);
        IOnMessageReceivedListener listener = new IOnMessageReceivedListener() {
            @Override
            public void onMessageReceived(int associationId, byte[] data) throws RemoteException {
                synchronized (mTransports) {
                    onPlatformInfoReceived(associationId, data);
                }
            }

            @Override
            public IBinder asBinder() {
                return null;
            }
        };
        mTempTransport.addListener(MESSAGE_REQUEST_PLATFORM_INFO, listener);
        mTempTransport.start();

        int sdk = Build.VERSION.SDK_INT;
        String release = Build.VERSION.RELEASE;
        // data format: | SDK_INT (int) | release length (int) | release |
        final ByteBuffer data = ByteBuffer.allocate(4 + 4 + release.getBytes().length)
                .putInt(sdk)
                .putInt(release.getBytes().length)
                .put(release.getBytes());

        // TODO: it should check if preSharedKey is given
        try {
            mTempTransport.sendMessage(MESSAGE_REQUEST_PLATFORM_INFO, data.array());
        } catch (IOException e) {
            Slog.e(TAG, "Failed to exchange platform info");
        }
    }

    /**
     * Depending on the remote platform info to decide which transport should be created
     */
    private void onPlatformInfoReceived(int associationId, byte[] data) {
        if (mTempTransport.getAssociationId() != associationId) {
            return;
        }
        // TODO: it should check if preSharedKey is given

        ByteBuffer buffer = ByteBuffer.wrap(data);
        int remoteSdk = buffer.getInt();
        byte[] remoteRelease = new byte[buffer.getInt()];
        buffer.get(remoteRelease);

        Slog.i(TAG, "Remote device SDK: " + remoteSdk + ", release:" + new String(remoteRelease));

        Transport transport = mTempTransport;
        mTempTransport.stop();

        int sdk = Build.VERSION.SDK_INT;
        String release = Build.VERSION.RELEASE;

        if (sdk < SECURE_CHANNEL_AVAILABLE_SDK || remoteSdk < SECURE_CHANNEL_AVAILABLE_SDK) {
            // If either device is Android T or below, use raw channel
            // TODO: depending on the release version, either
            //       1) using a RawTransport for old T versions
            //       2) or an Ukey2 handshaked transport for UKey2 backported T versions
            Slog.d(TAG, "Secure channel is not supported. Using raw transport");
            transport = new RawTransport(transport.getAssociationId(), transport.getFd(), mContext);
            // If secure transport is explicitly disabled for testing, use raw transport
            Slog.i(TAG, "Secure channel is disabled. Creating raw transport");
            transport = new RawTransport(associationId, fd, mContext);
        } else if (Build.isDebuggable()) {
            // If device is debug build, use hardcoded test key for authentication
            Slog.d(TAG, "Creating an unauthenticated secure channel");
            final byte[] testKey = "CDM".getBytes(StandardCharsets.UTF_8);
            transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
                    mContext, testKey, null);
        } else if (sdk == NON_ANDROID || remoteSdk == NON_ANDROID) {
            transport = new SecureTransport(associationId, fd, mContext, testKey, null);
        } else if (preSharedKey != null) {
            // If either device is not Android, then use app-specific pre-shared key
            // TODO: pass in a real preSharedKey
            Slog.d(TAG, "Creating a PSK-authenticated secure channel");
            transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
                    mContext, new byte[0], null);
            transport = new SecureTransport(associationId, fd, mContext, preSharedKey, null);
        } else {
            // If none of the above applies, then use secure channel with attestation verification
            Slog.d(TAG, "Creating a secure channel");
            transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
                    mContext);
            transport = new SecureTransport(associationId, fd, mContext);
        }

        addMessageListenersToTransport(transport);
        transport.start();
        synchronized (mTransports) {
            mTransports.put(transport.getAssociationId(), transport);
            mTransports.put(associationId, transport);
        }
        // Doesn't need to notifyTransportsChanged here, it'll be done in attachSystemDataTransport

    }

    public Future<?> requestPermissionRestore(int associationId, byte[] data) {
+3 −3
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ class RawTransport extends Transport {
    }

    @Override
    public void start() {
    void start() {
        if (DEBUG) {
            Slog.d(TAG, "Starting raw transport.");
        }
@@ -54,7 +54,7 @@ class RawTransport extends Transport {
    }

    @Override
    public void stop() {
    void stop() {
        if (DEBUG) {
            Slog.d(TAG, "Stopping raw transport.");
        }
@@ -62,7 +62,7 @@ class RawTransport extends Transport {
    }

    @Override
    public void close() {
    void close() {
        stop();

        if (DEBUG) {
+3 −3
Original line number Diff line number Diff line
@@ -51,18 +51,18 @@ class SecureTransport extends Transport implements SecureChannel.Callback {
    }

    @Override
    public void start() {
    void start() {
        mSecureChannel.start();
    }

    @Override
    public void stop() {
    void stop() {
        mSecureChannel.stop();
        mShouldProcessRequests = false;
    }

    @Override
    public void close() {
    void close() {
        mSecureChannel.close();
        mShouldProcessRequests = false;
    }
+3 −9
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@ public abstract class Transport {
    protected static final boolean DEBUG = Build.IS_DEBUGGABLE;

    static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
    public static final int MESSAGE_REQUEST_PLATFORM_INFO = 0x63807073; // ?PFI
    public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS
    public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES

@@ -113,17 +112,17 @@ public abstract class Transport {
    /**
     * Start listening to messages.
     */
    public abstract void start();
    abstract void start();

    /**
     * Soft stop listening to the incoming data without closing the streams.
     */
    public abstract void stop();
    abstract void stop();

    /**
     * Stop listening to the incoming data and close the streams.
     */
    public abstract void close();
    abstract void close();

    protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
            throws IOException;
@@ -183,11 +182,6 @@ public abstract class Transport {
                sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data);
                break;
            }
            case MESSAGE_REQUEST_PLATFORM_INFO: {
                callback(message, data);
                // DO NOT SEND A RESPONSE!
                break;
            }
            case MESSAGE_REQUEST_CONTEXT_SYNC: {
                callback(message, data);
                sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);