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

Commit 9868762e authored by Eran Messeri's avatar Eran Messeri Committed by Android (Google) Code Review
Browse files

Merge "Implement Enrollment-Specific ID"

parents ed647d46 a844c598
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6925,6 +6925,7 @@ package android.app.admin {
    method @NonNull public java.util.List<java.lang.String> getDelegatedScopes(@Nullable android.content.ComponentName, @NonNull String);
    method public CharSequence getDeviceOwnerLockScreenInfo();
    method public CharSequence getEndUserSessionMessage(@NonNull android.content.ComponentName);
    method @NonNull public String getEnrollmentSpecificId();
    method @Nullable public android.app.admin.FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(@Nullable android.content.ComponentName);
    method @Nullable public String getGlobalPrivateDnsHost(@NonNull android.content.ComponentName);
    method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName);
@@ -7075,6 +7076,7 @@ package android.app.admin {
    method @NonNull public java.util.List<java.lang.String> setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
    method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
    method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
    method public void setOrganizationId(@NonNull String);
    method public void setOrganizationName(@NonNull android.content.ComponentName, @Nullable CharSequence);
    method public void setOverrideApnsEnabled(@NonNull android.content.ComponentName, boolean);
    method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean);
+62 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.IServiceConnection;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
import android.app.admin.SecurityLog.SecurityEvent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -12814,4 +12813,66 @@ public class DevicePolicyManager {
            }
        }
    }
    /**
     * Returns an enrollment-specific identifier of this device, which is guaranteed to be the same
     * value for the same device, enrolled into the same organization by the same managing app.
     * This identifier is high-entropy, useful for uniquely identifying individual devices within
     * the same organisation.
     * It is available both in a work profile and on a fully-managed device.
     * The identifier would be consistent even if the work profile is removed and enrolled again
     * (to the same organization), or the device is factory reset and re-enrolled.
     * Can only be called by the Profile Owner or Device Owner, if the
     * {@link #setOrganizationId(String)} was previously called.
     * If {@link #setOrganizationId(String)} was not called, then the returned value will be an
     * empty string.
     *
     * @return A stable, enrollment-specific identifier.
     * @throws SecurityException if the caller is not a profile owner or device owner.
     */
    @NonNull public String getEnrollmentSpecificId() {
        if (mService == null) {
            return "";
        }
        try {
            return mService.getEnrollmentSpecificId();
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }
    /**
     * Sets the Enterprise ID for the work profile or managed device. This is a requirement for
     * generating an enrollment-specific ID for the device, see {@link #getEnrollmentSpecificId()}.
     *
     * It is recommended that the Enterprise ID is at least 6 characters long, and no more than
     * 64 characters.
     *
     * @param enterpriseId An identifier of the organization this work profile or device is
     *                     enrolled into.
     */
    public void setOrganizationId(@NonNull String enterpriseId) {
        setOrganizationIdForUser(mContext.getPackageName(), enterpriseId, myUserId());
    }
    /**
     * Sets the Enterprise ID for the work profile or managed device. This is a requirement for
     * generating an enrollment-specific ID for the device, see
     * {@link #getEnrollmentSpecificId()}.
     *
     * @hide
     */
    public void setOrganizationIdForUser(@NonNull String packageName,
            @NonNull String enterpriseId, @UserIdInt int userId) {
        if (mService == null) {
            return;
        }
        try {
            mService.setOrganizationIdForUser(packageName, enterpriseId, userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -489,4 +489,7 @@ interface IDevicePolicyManager {
    boolean canProfileOwnerResetPasswordWhenLocked(int userId);

    void setNextOperationSafety(int operation, boolean safe);

    String getEnrollmentSpecificId();
    void setOrganizationIdForUser(in String callerPackage, in String enterpriseId, int userId);
}
+10 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.security.identity;

import android.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
@@ -28,7 +30,10 @@ import java.util.Collection;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

class Util {
/**
 * @hide
 */
public class Util {
    private static final String TAG = "Util";

    static int[] integerCollectionToArray(Collection<Integer> collection) {
@@ -91,8 +96,9 @@ class Util {
     *                     255.DigestSize, where DigestSize is the size of the underlying HMAC.
     * @return size pseudorandom bytes.
     */
    static byte[] computeHkdf(
            String macAlgorithm, final byte[] ikm, final byte[] salt, final byte[] info, int size) {
    @NonNull public static byte[] computeHkdf(
            @NonNull String macAlgorithm, @NonNull final byte[] ikm, @NonNull final byte[] salt,
            @NonNull final byte[] info, int size) {
        Mac mac = null;
        try {
            mac = Mac.getInstance(macAlgorithm);
@@ -137,4 +143,5 @@ class Util {
        }
    }

    private Util() {}
}
+36 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ class ActiveAdmin {
    private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
    private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
    private static final String TAG_PASSWORD_COMPLEXITY = "password-complexity";
    private static final String TAG_ORGANIZATION_ID = "organization-id";
    private static final String TAG_ENROLLMENT_SPECIFIC_ID = "enrollment-specific-id";
    private static final String ATTR_VALUE = "value";
    private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
    private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
@@ -273,6 +275,8 @@ class ActiveAdmin {
    public String mAlwaysOnVpnPackage;
    public boolean mAlwaysOnVpnLockdown;
    boolean mCommonCriteriaMode;
    public String mOrganizationId;
    public String mEnrollmentSpecificId;

    ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
        this.info = info;
@@ -533,6 +537,12 @@ class ActiveAdmin {
        if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
            writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
        }
        if (!TextUtils.isEmpty(mOrganizationId)) {
            writeTextToXml(out, TAG_ORGANIZATION_ID, mOrganizationId);
        }
        if (!TextUtils.isEmpty(mEnrollmentSpecificId)) {
            writeTextToXml(out, TAG_ENROLLMENT_SPECIFIC_ID, mEnrollmentSpecificId);
        }
    }

    void writeTextToXml(TypedXmlSerializer out, String tag, String text) throws IOException {
@@ -766,6 +776,22 @@ class ActiveAdmin {
                mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
            } else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
                mPasswordComplexity = parser.getAttributeInt(null, ATTR_VALUE);
            } else if (TAG_ORGANIZATION_ID.equals(tag)) {
                type = parser.next();
                if (type == TypedXmlPullParser.TEXT) {
                    mOrganizationId = parser.getText();
                } else {
                    Log.w(DevicePolicyManagerService.LOG_TAG,
                            "Missing Organization ID.");
                }
            } else if (TAG_ENROLLMENT_SPECIFIC_ID.equals(tag)) {
                type = parser.next();
                if (type == TypedXmlPullParser.TEXT) {
                    mEnrollmentSpecificId = parser.getText();
                } else {
                    Log.w(DevicePolicyManagerService.LOG_TAG,
                            "Missing Enrollment-specific ID.");
                }
            } else {
                Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
                XmlUtils.skipCurrentTag(parser);
@@ -1107,5 +1133,15 @@ class ActiveAdmin {

        pw.print("mPasswordComplexity=");
        pw.println(mPasswordComplexity);

        if (!TextUtils.isEmpty(mOrganizationId)) {
            pw.print("mOrganizationId=");
            pw.println(mOrganizationId);
        }

        if (!TextUtils.isEmpty(mEnrollmentSpecificId)) {
            pw.print("mEnrollmentSpecificId=");
            pw.println(mEnrollmentSpecificId);
        }
    }
}
Loading