summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eran Messeri <eranm@google.com> 2017-11-22 17:12:29 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-11-22 17:12:29 +0000
commit3daba14f2598956eb2b303e34e39717c326cb8df (patch)
tree34af17993905fdc6aa33afc8fbbbf4b22211d7dd
parent7430d8d89667a39c5f993dc46c00c98814382f72 (diff)
parent19d19048e46a44f9cd92f9b3c2b45d9603283f15 (diff)
Merge "DevicePolicyManager: Make installed keys user-selectable by default."
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java43
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java4
6 files changed, 50 insertions, 3 deletions
diff --git a/api/current.txt b/api/current.txt
index e5f41be47f50..ec13b5560d37 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6377,6 +6377,7 @@ package android.app.admin {
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index e08e17272743..ce3d27795d22 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6605,6 +6605,7 @@ package android.app.admin {
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 67925981b4d7..8a718f588d70 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6446,6 +6446,7 @@ package android.app.admin {
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f0226b7e848f..0bca96907988 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3858,6 +3858,47 @@ public class DevicePolicyManager {
*/
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess) {
+ return installKeyPair(admin, privKey, certs, alias, requestAccess, true);
+ }
+
+ /**
+ * Called by a device or profile owner, or delegated certificate installer, to install a
+ * certificate chain and corresponding private key for the leaf certificate. All apps within the
+ * profile will be able to access the certificate chain and use the private key, given direct
+ * user approval (if the user is allowed to select the private key).
+ *
+ * <p>The caller of this API may grant itself access to the certificate and private key
+ * immediately, without user approval. It is a best practice not to request this unless strictly
+ * necessary since it opens up additional security vulnerabilities.
+ *
+ * <p>Whether this key is offered to the user for approval at all or not depends on the
+ * {@code isUserSelectable} parameter.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
+ * @param privKey The private key to install.
+ * @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 alias The private key alias under which to install the certificate. If a certificate
+ * with that alias already exists, it will be overwritten.
+ * @param requestAccess {@code true} to request that the calling app be granted access to the
+ * credentials immediately. Otherwise, access to the credentials will be gated by user
+ * approval.
+ * @param isUserSelectable {@code true} to indicate that a user can select this key via the
+ * Certificate Selection prompt, false to indicate that this key can only be granted
+ * access by implementing
+ * {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias}.
+ * @return {@code true} if the keys were installed, {@code false} otherwise.
+ * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+ * owner.
+ * @see android.security.KeyChain#getCertificateChain
+ * @see #setDelegatedScopes
+ * @see #DELEGATION_CERT_INSTALL
+ */
+ public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
+ @NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess,
+ boolean isUserSelectable) {
throwIfParentInstance("installKeyPair");
try {
final byte[] pemCert = Credentials.convertToPem(certs[0]);
@@ -3868,7 +3909,7 @@ public class DevicePolicyManager {
final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm())
.getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
return mService.installKeyPair(admin, mContext.getPackageName(), pkcs8Key, pemCert,
- pemChain, alias, requestAccess);
+ pemChain, alias, requestAccess, isUserSelectable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index be0b9205bcdd..b7740e9e7314 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -162,7 +162,8 @@ interface IDevicePolicyManager {
boolean isCaCertApproved(in String alias, int userHandle);
boolean installKeyPair(in ComponentName who, in String callerPackage, in byte[] privKeyBuffer,
- in byte[] certBuffer, in byte[] certChainBuffer, String alias, boolean requestAccess);
+ in byte[] certBuffer, in byte[] certChainBuffer, String alias, boolean requestAccess,
+ boolean isUserSelectable);
boolean removeKeyPair(in ComponentName who, in String callerPackage, String alias);
void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2d8a0ee02225..60c36d1b7203 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4917,7 +4917,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public boolean installKeyPair(ComponentName who, String callerPackage, byte[] privKey,
- byte[] cert, byte[] chain, String alias, boolean requestAccess) {
+ byte[] cert, byte[] chain, String alias, boolean requestAccess,
+ boolean isUserSelectable) {
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_CERT_INSTALL);
@@ -4935,6 +4936,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (requestAccess) {
keyChain.setGrant(callingUid, alias, true);
}
+ keyChain.setUserSelectable(alias, isUserSelectable);
return true;
} catch (RemoteException e) {
Log.e(LOG_TAG, "Installing certificate", e);