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

Commit ecf0f22e authored by Eran Messeri's avatar Eran Messeri
Browse files

DPM: Implement installing certificates for generated keys

Add a new method in the DevicePolicyManager to associate certificates (and
set the user-visibility) with a given key alias.
Conceptually, the new method, setKeyPairCertificate is very similar to
installKeyPair, except it does not install a key, only certificates.

(The new setKeyPairCertificate, together with generateKeyPair is
functionally equivalent to installKeyPair, except the keys are generated
in hardware rather than supplied externally).

Bug: 63388672
Test: cts-tradefed run commandAndExit cts-dev -a armeabi-v7a -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement -l DEBUG
Change-Id: Idbfe151f6e5311766decbc1a010bff78dc60249f
parent 171fec8c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6450,6 +6450,7 @@ package android.app.admin {
    method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
    method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
    method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
    method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean);
    method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
    method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
    method public void setLockTaskFeatures(android.content.ComponentName, int);
+46 −0
Original line number Diff line number Diff line
@@ -4062,6 +4062,52 @@ public class DevicePolicyManager {
        return null;
    }


    /**
     * Called by a device or profile owner, or delegated certificate installer, to associate
     * certificates with a key pair that was generated using {@link #generateKeyPair}, and
     * set whether the key is available for the user to choose in the certificate selection
     * prompt.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
     *            {@code null} if calling from a delegated certificate installer.
     * @param alias The private key alias under which to install the certificate. The {@code alias}
     *        should denote an existing private key. If a certificate with that alias already
     *        exists, it will be overwritten.
     * @param certs The certificate chain to install. The chain should start with the leaf
     *        certificate and include the chain of trust in order. This will be returned by
     *        {@link android.security.KeyChain#getCertificateChain}.
     * @param isUserSelectable {@code true} to indicate that a user can select this key via the
     *        certificate selection prompt, {@code false} to indicate that this key can only be
     *        granted access by implementing
     *        {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias}.
     * @return {@code true} if the provided {@code alias} exists and the certificates has been
     *        successfully associated with it, {@code false} otherwise.
     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
     *         owner, or {@code admin} is null but the calling application is not a delegated
     *         certificate installer.
     */
    public boolean setKeyPairCertificate(@Nullable ComponentName admin,
            @NonNull String alias, @NonNull List<Certificate> certs, boolean isUserSelectable) {
        throwIfParentInstance("setKeyPairCertificate");
        try {
            final byte[] pemCert = Credentials.convertToPem(certs.get(0));
            byte[] pemChain = null;
            if (certs.size() > 1) {
                pemChain = Credentials.convertToPem(
                        certs.subList(1, certs.size()).toArray(new Certificate[0]));
            }
            return mService.setKeyPairCertificate(admin, mContext.getPackageName(), alias, pemCert,
                    pemChain, isUserSelectable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (CertificateException | IOException e) {
            Log.w(TAG, "Could not pem-encode certificate", e);
        }
        return false;
    }


    /**
     * @return the alias of a given CA certificate in the certificate store, or {@code null} if it
     * doesn't exist.
+2 −0
Original line number Diff line number Diff line
@@ -171,6 +171,8 @@ interface IDevicePolicyManager {
    boolean generateKeyPair(in ComponentName who, in String callerPackage, in String algorithm,
            in ParcelableKeyGenParameterSpec keySpec,
            out KeymasterCertificateChain attestationChain);
    boolean setKeyPairCertificate(in ComponentName who, in String callerPackage, in String alias,
            in byte[] certBuffer, in byte[] certChainBuffer, boolean isUserSelectable);
    void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback);

    void setDelegatedScopes(in ComponentName who, in String delegatePackage, in List<String> scopes);
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ interface IKeyChainService {

    boolean generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec);
    boolean attestKey(in String alias, in byte[] challenge, out KeymasterCertificateChain chain);
    boolean setKeyPairCertificate(String alias, in byte[] userCert, in byte[] certChain);

    // APIs used by CertInstaller and DevicePolicyManager
    String installCaCertificate(in byte[] caCertificate);
+5 −0
Original line number Diff line number Diff line
@@ -71,4 +71,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
    public boolean isUsingUnifiedPassword(ComponentName who) {
        return true;
    }

    public boolean setKeyPairCertificate(ComponentName who, String callerPackage, String alias,
            byte[] cert, byte[] chain, boolean isUserSelectable) {
        return false;
    }
}
Loading