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

Commit 3f1ad878 authored by Raphael Kim's avatar Raphael Kim Committed by Android (Google) Code Review
Browse files

Merge changes from topic "avf-extend" into main

* changes:
  [W][CDM] Initialize a transport with extended patch diff if device is WEARABLE_SENSING
  [W][CDM] Add flagging support for transport attachment
parents bb238222 98d02a21
Loading
Loading
Loading
Loading
+71 −3
Original line number Diff line number Diff line
@@ -277,6 +277,23 @@ public final class CompanionDeviceManager {
     */
    public static final int MESSAGE_ONEWAY_TO_WEARABLE = 0x43847987; // +TOW


    /** @hide */
    @IntDef(flag = true, prefix = { "TRANSPORT_FLAG_" }, value = {
            TRANSPORT_FLAG_EXTEND_PATCH_DIFF,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransportFlags {}

    /**
     * A security flag that allows transports to be attached to devices that may be more vulnerable
     * due to infrequent updates. Can only be used for associations with
     * {@link AssociationRequest#DEVICE_PROFILE_WEARABLE_SENSING} device profile.
     *
     * @hide
     */
    public static final int TRANSPORT_FLAG_EXTEND_PATCH_DIFF = 1;

    /**
     * Callback for applications to receive updates about and the outcome of
     * {@link AssociationRequest} issued via {@code associate()} call.
@@ -1452,7 +1469,52 @@ public final class CompanionDeviceManager {
            }

            try {
                final Transport transport = new Transport(associationId, in, out);
                final Transport transport = new Transport(associationId, in, out, 0);
                mTransports.put(associationId, transport);
                transport.start();
            } catch (IOException e) {
                throw new RuntimeException("Failed to attach transport", e);
            }
        }
    }

    /**
     * Attach a bidirectional communication stream to be used as a transport channel for
     * transporting system data between associated devices. Flags can be provided to further
     * customize the behavior of the transport.
     *
     * @param associationId id of the associated device.
     * @param in Already connected stream of data incoming from remote
     *           associated device.
     * @param out Already connected stream of data outgoing to remote associated
     *            device.
     * @param flags Flags to customize transport behavior.
     * @throws DeviceNotAssociatedException Thrown if the associationId was not previously
     * associated with this app.
     *
     * @see #buildPermissionTransferUserConsentIntent(int)
     * @see #startSystemDataTransfer(int, Executor, OutcomeReceiver)
     * @see #detachSystemDataTransport(int)
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES)
    public void attachSystemDataTransport(int associationId,
            @NonNull InputStream in,
            @NonNull OutputStream out,
            @TransportFlags int flags) throws DeviceNotAssociatedException {
        if (mService == null) {
            Log.w(TAG, "CompanionDeviceManager service is not available.");
            return;
        }

        synchronized (mTransports) {
            if (mTransports.contains(associationId)) {
                detachSystemDataTransport(associationId);
            }

            try {
                final Transport transport = new Transport(associationId, in, out, flags);
                mTransports.put(associationId, transport);
                transport.start();
            } catch (IOException e) {
@@ -1931,16 +1993,22 @@ public final class CompanionDeviceManager {
        private final int mAssociationId;
        private final InputStream mRemoteIn;
        private final OutputStream mRemoteOut;
        private final int mFlags;

        private InputStream mLocalIn;
        private OutputStream mLocalOut;

        private volatile boolean mStopped;

        public Transport(int associationId, InputStream remoteIn, OutputStream remoteOut) {
        Transport(int associationId, InputStream remoteIn, OutputStream remoteOut) {
            this(associationId, remoteIn, remoteOut, 0);
        }

        Transport(int associationId, InputStream remoteIn, OutputStream remoteOut, int flags) {
            mAssociationId = associationId;
            mRemoteIn = remoteIn;
            mRemoteOut = remoteOut;
            mFlags = flags;
        }

        public void start() throws IOException {
@@ -1957,7 +2025,7 @@ public final class CompanionDeviceManager {

            try {
                mService.attachSystemDataTransport(mContext.getOpPackageName(),
                        mContext.getUserId(), mAssociationId, remoteFd);
                        mContext.getUserId(), mAssociationId, remoteFd, mFlags);
            } catch (RemoteException e) {
                throw new IOException("Failed to configure transport", e);
            }
+1 −1
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ interface ICompanionDeviceManager {
        in ISystemDataTransferCallback callback);

    @EnforcePermission("DELIVER_COMPANION_MESSAGES")
    void attachSystemDataTransport(String packageName, int userId, int associationId, in ParcelFileDescriptor fd);
    void attachSystemDataTransport(String packageName, int userId, int associationId, in ParcelFileDescriptor fd, int flags);

    @EnforcePermission("DELIVER_COMPANION_MESSAGES")
    void detachSystemDataTransport(String packageName, int userId, int associationId);
+2 −2
Original line number Diff line number Diff line
@@ -588,10 +588,10 @@ public class CompanionDeviceManagerService extends SystemService {
        @Override
        @EnforcePermission(DELIVER_COMPANION_MESSAGES)
        public void attachSystemDataTransport(String packageName, int userId, int associationId,
                ParcelFileDescriptor fd) {
                                              ParcelFileDescriptor fd, int flags) {
            attachSystemDataTransport_enforcePermission();

            mTransportManager.attachSystemDataTransport(associationId, fd);
            mTransportManager.attachSystemDataTransport(associationId, fd, flags);
        }

        @Override
+24 −2
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.server.companion.securechannel;

import static android.companion.CompanionDeviceManager.TRANSPORT_FLAG_EXTEND_PATCH_DIFF;
import static android.security.attestationverification.AttestationVerificationManager.PARAM_CHALLENGE;
import static android.security.attestationverification.AttestationVerificationManager.PARAM_MAX_PATCH_LEVEL_DIFF_MONTHS;
import static android.security.attestationverification.AttestationVerificationManager.PROFILE_PEER_DEVICE;
import static android.security.attestationverification.AttestationVerificationManager.TYPE_CHALLENGE;

@@ -34,15 +36,21 @@ import java.util.function.BiConsumer;

/**
 * Helper class to perform attestation verification synchronously.
 *
 * @hide
 */
public class AttestationVerifier {
    private static final long ATTESTATION_VERIFICATION_TIMEOUT_SECONDS = 10; // 10 seconds
    private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";

    private static final int EXTENDED_PATCH_LEVEL_DIFF_MONTHS = 24; // 2 years

    private final Context mContext;
    private final int mFlags;

    AttestationVerifier(Context context) {
    AttestationVerifier(Context context, int flags) {
        this.mContext = context;
        this.mFlags = flags;
    }

    /**
@@ -59,10 +67,13 @@ public class AttestationVerifier {
            @NonNull byte[] remoteAttestation,
            @NonNull byte[] attestationChallenge
    ) throws SecureChannelException {
        Bundle requirements = new Bundle();
        final Bundle requirements = new Bundle();
        requirements.putByteArray(PARAM_CHALLENGE, attestationChallenge);
        requirements.putBoolean(PARAM_OWNED_BY_SYSTEM, true); // Custom parameter for CDM

        // Apply flags to verifier requirements
        updateRequirements(requirements);

        // Synchronously execute attestation verification.
        AtomicInteger verificationResult = new AtomicInteger(0);
        CountDownLatch verificationFinished = new CountDownLatch(1);
@@ -96,4 +107,15 @@ public class AttestationVerifier {

        return verificationResult.get();
    }

    private void updateRequirements(Bundle requirements) {
        if (mFlags == 0) {
            return;
        }

        if ((mFlags & TRANSPORT_FLAG_EXTEND_PATCH_DIFF) > 0) {
            requirements.putInt(PARAM_MAX_PATCH_LEVEL_DIFF_MONTHS,
                    EXTENDED_PATCH_LEVEL_DIFF_MONTHS);
        }
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public class SecureChannel {
    private final Callback mCallback;
    private final byte[] mPreSharedKey;
    private final AttestationVerifier mVerifier;
    private final int mFlags;

    private volatile boolean mStopped;
    private volatile boolean mInProgress;
@@ -89,7 +90,7 @@ public class SecureChannel {
            @NonNull Callback callback,
            @NonNull byte[] preSharedKey
    ) {
        this(in, out, callback, preSharedKey, null);
        this(in, out, callback, preSharedKey, null, 0);
    }

    /**
@@ -100,14 +101,16 @@ public class SecureChannel {
     * @param out output stream from which data is sent out
     * @param callback subscription to received messages from the channel
     * @param context context for fetching the Attestation Verifier Framework system service
     * @param flags flags for custom security settings on the channel
     */
    public SecureChannel(
            @NonNull final InputStream in,
            @NonNull final OutputStream out,
            @NonNull Callback callback,
            @NonNull Context context
            @NonNull Context context,
            int flags
    ) {
        this(in, out, callback, null, new AttestationVerifier(context));
        this(in, out, callback, null, new AttestationVerifier(context, flags), flags);
    }

    public SecureChannel(
@@ -115,13 +118,15 @@ public class SecureChannel {
            final OutputStream out,
            Callback callback,
            byte[] preSharedKey,
            AttestationVerifier verifier
            AttestationVerifier verifier,
            int flags
    ) {
        this.mInput = in;
        this.mOutput = out;
        this.mCallback = callback;
        this.mPreSharedKey = preSharedKey;
        this.mVerifier = verifier;
        this.mFlags = flags;
    }

    /**
Loading