Loading api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -6323,6 +6323,7 @@ package android.app.admin { method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int); method public void enableSystemApp(android.content.ComponentName, java.lang.String); method public int enableSystemApp(android.content.ComponentName, android.content.Intent); method public android.security.AttestedKeyPair generateKeyPair(android.content.ComponentName, java.lang.String, android.security.keystore.KeyGenParameterSpec); method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public java.util.Set<java.lang.String> getAffiliationIds(android.content.ComponentName); Loading Loading @@ -37149,6 +37150,11 @@ package android.sax { package android.security { public final class AttestedKeyPair { method public java.util.List<java.security.cert.Certificate> getAttestationRecord(); method public java.security.KeyPair getKeyPair(); } public final class KeyChain { ctor public KeyChain(); method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String); core/java/android/app/admin/DevicePolicyManager.java +50 −0 Original line number Diff line number Diff line Loading @@ -57,7 +57,12 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.Directory; import android.security.AttestedKeyPair; import android.security.Credentials; import android.security.KeyChain; import android.security.KeyChainException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.service.restrictions.RestrictionsReceiver; import android.telephony.TelephonyManager; import android.util.ArraySet; Loading @@ -75,6 +80,7 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetSocketAddress; import java.net.Proxy; import java.security.KeyFactory; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; Loading Loading @@ -3942,6 +3948,50 @@ public class DevicePolicyManager { } } /** * Called by a device or profile owner, or delegated certificate installer, to generate a * new private/public key pair. If the device supports key generation via secure hardware, * this method is useful for creating a key in KeyChain that never left the secure hardware. * * Access to the key is controlled the same way as in {@link #installKeyPair}. * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}. * @param keySpec Specification of the key to generate, see * {@link java.security.KeyPairGenerator}. * @return A non-null {@code AttestedKeyPair} if the key generation succeeded, null otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile * owner. * @throws IllegalArgumentException if the alias in {@code keySpec} is empty, or if the * algorithm specification in {@code keySpec} is not {@code RSAKeyGenParameterSpec} * or {@code ECGenParameterSpec}. */ public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin, @NonNull String algorithm, @NonNull KeyGenParameterSpec keySpec) { throwIfParentInstance("generateKeyPair"); try { final ParcelableKeyGenParameterSpec parcelableSpec = new ParcelableKeyGenParameterSpec(keySpec); final boolean success = mService.generateKeyPair( admin, mContext.getPackageName(), algorithm, parcelableSpec); if (!success) { Log.e(TAG, "Error generating key via DevicePolicyManagerService."); return null; } final KeyPair keyPair = KeyChain.getKeyPair(mContext, keySpec.getKeystoreAlias()); return new AttestedKeyPair(keyPair, null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (KeyChainException e) { Log.w(TAG, "Failed to generate key", e); } catch (InterruptedException e) { Log.w(TAG, "Interrupted while generating key", e); Thread.currentThread().interrupt(); } return null; } /** * @return the alias of a given CA certificate in the certificate store, or {@code null} if it * doesn't exist. Loading core/java/android/app/admin/IDevicePolicyManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.os.Bundle; import android.os.PersistableBundle; import android.os.RemoteCallback; import android.os.UserHandle; import android.security.keystore.ParcelableKeyGenParameterSpec; import java.util.List; Loading Loading @@ -165,6 +166,7 @@ interface IDevicePolicyManager { in byte[] certBuffer, in byte[] certChainBuffer, String alias, boolean requestAccess, boolean isUserSelectable); boolean removeKeyPair(in ComponentName who, in String callerPackage, String alias); boolean generateKeyPair(in ComponentName who, in String callerPackage, in String algorithm, in ParcelableKeyGenParameterSpec keySpec); void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback); void setDelegatedScopes(in ComponentName who, in String delegatePackage, in List<String> scopes); Loading keystore/java/android/security/AttestedKeyPair.java 0 → 100644 +75 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.security; import java.security.KeyPair; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The {@code AttestedKeyPair} class contains a {@code KeyPair} instance of * keys generated by Keystore and owned by KeyChain, as well as an attestation * record for the key. * * <p>Such keys can be obtained by calling * {@link android.app.admin.DevicePolicyManager#generateKeyPair}. */ public final class AttestedKeyPair { private final KeyPair mKeyPair; private final Certificate[] mAttestationRecord; /** * @hide Only created by the platform, no need to expose as public API. */ public AttestedKeyPair(KeyPair keyPair, Certificate[] attestationRecord) { mKeyPair = keyPair; mAttestationRecord = attestationRecord; } /** * Returns the generated key pair associated with the attestation record * in this instance. */ public KeyPair getKeyPair() { return mKeyPair; } /** * Returns the attestation record for the key pair in this instance. * * The attestation record is a chain of certificates. The leaf certificate links to the public * key of this key pair and other properties of the key or the device. If the key is in secure * hardware, and if the secure hardware supports attestation, the leaf certificate will be * signed by a chain of certificates rooted at a trustworthy CA key. Otherwise the chain will be * rooted at an untrusted certificate. * * The attestation record could be for properties of the key, or include device identifiers. * * See {@link android.security.keystore.KeyGenParameterSpec.Builder#setAttestationChallenge} * and <a href="https://developer.android.com/training/articles/security-key-attestation.html"> * Key Attestation</a> for the format of the attestation record inside the certificate. */ public List<Certificate> getAttestationRecord() { if (mAttestationRecord == null) { return new ArrayList(); } return Arrays.asList(mAttestationRecord); } } keystore/java/android/security/IKeyChainService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.security; import android.content.pm.StringParceledListSlice; import android.security.keystore.ParcelableKeyGenParameterSpec; /** * Caller is required to ensure that {@link KeyStore#unlock Loading @@ -31,6 +32,8 @@ interface IKeyChainService { boolean isUserSelectable(String alias); void setUserSelectable(String alias, boolean isUserSelectable); boolean generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec); // APIs used by CertInstaller and DevicePolicyManager String installCaCertificate(in byte[] caCertificate); Loading Loading
api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -6323,6 +6323,7 @@ package android.app.admin { method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int); method public void enableSystemApp(android.content.ComponentName, java.lang.String); method public int enableSystemApp(android.content.ComponentName, android.content.Intent); method public android.security.AttestedKeyPair generateKeyPair(android.content.ComponentName, java.lang.String, android.security.keystore.KeyGenParameterSpec); method public java.lang.String[] getAccountTypesWithManagementDisabled(); method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public java.util.Set<java.lang.String> getAffiliationIds(android.content.ComponentName); Loading Loading @@ -37149,6 +37150,11 @@ package android.sax { package android.security { public final class AttestedKeyPair { method public java.util.List<java.security.cert.Certificate> getAttestationRecord(); method public java.security.KeyPair getKeyPair(); } public final class KeyChain { ctor public KeyChain(); method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
core/java/android/app/admin/DevicePolicyManager.java +50 −0 Original line number Diff line number Diff line Loading @@ -57,7 +57,12 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.Directory; import android.security.AttestedKeyPair; import android.security.Credentials; import android.security.KeyChain; import android.security.KeyChainException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.service.restrictions.RestrictionsReceiver; import android.telephony.TelephonyManager; import android.util.ArraySet; Loading @@ -75,6 +80,7 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetSocketAddress; import java.net.Proxy; import java.security.KeyFactory; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; Loading Loading @@ -3942,6 +3948,50 @@ public class DevicePolicyManager { } } /** * Called by a device or profile owner, or delegated certificate installer, to generate a * new private/public key pair. If the device supports key generation via secure hardware, * this method is useful for creating a key in KeyChain that never left the secure hardware. * * Access to the key is controlled the same way as in {@link #installKeyPair}. * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}. * @param keySpec Specification of the key to generate, see * {@link java.security.KeyPairGenerator}. * @return A non-null {@code AttestedKeyPair} if the key generation succeeded, null otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile * owner. * @throws IllegalArgumentException if the alias in {@code keySpec} is empty, or if the * algorithm specification in {@code keySpec} is not {@code RSAKeyGenParameterSpec} * or {@code ECGenParameterSpec}. */ public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin, @NonNull String algorithm, @NonNull KeyGenParameterSpec keySpec) { throwIfParentInstance("generateKeyPair"); try { final ParcelableKeyGenParameterSpec parcelableSpec = new ParcelableKeyGenParameterSpec(keySpec); final boolean success = mService.generateKeyPair( admin, mContext.getPackageName(), algorithm, parcelableSpec); if (!success) { Log.e(TAG, "Error generating key via DevicePolicyManagerService."); return null; } final KeyPair keyPair = KeyChain.getKeyPair(mContext, keySpec.getKeystoreAlias()); return new AttestedKeyPair(keyPair, null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (KeyChainException e) { Log.w(TAG, "Failed to generate key", e); } catch (InterruptedException e) { Log.w(TAG, "Interrupted while generating key", e); Thread.currentThread().interrupt(); } return null; } /** * @return the alias of a given CA certificate in the certificate store, or {@code null} if it * doesn't exist. Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.os.Bundle; import android.os.PersistableBundle; import android.os.RemoteCallback; import android.os.UserHandle; import android.security.keystore.ParcelableKeyGenParameterSpec; import java.util.List; Loading Loading @@ -165,6 +166,7 @@ interface IDevicePolicyManager { in byte[] certBuffer, in byte[] certChainBuffer, String alias, boolean requestAccess, boolean isUserSelectable); boolean removeKeyPair(in ComponentName who, in String callerPackage, String alias); boolean generateKeyPair(in ComponentName who, in String callerPackage, in String algorithm, in ParcelableKeyGenParameterSpec keySpec); void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback); void setDelegatedScopes(in ComponentName who, in String delegatePackage, in List<String> scopes); Loading
keystore/java/android/security/AttestedKeyPair.java 0 → 100644 +75 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.security; import java.security.KeyPair; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The {@code AttestedKeyPair} class contains a {@code KeyPair} instance of * keys generated by Keystore and owned by KeyChain, as well as an attestation * record for the key. * * <p>Such keys can be obtained by calling * {@link android.app.admin.DevicePolicyManager#generateKeyPair}. */ public final class AttestedKeyPair { private final KeyPair mKeyPair; private final Certificate[] mAttestationRecord; /** * @hide Only created by the platform, no need to expose as public API. */ public AttestedKeyPair(KeyPair keyPair, Certificate[] attestationRecord) { mKeyPair = keyPair; mAttestationRecord = attestationRecord; } /** * Returns the generated key pair associated with the attestation record * in this instance. */ public KeyPair getKeyPair() { return mKeyPair; } /** * Returns the attestation record for the key pair in this instance. * * The attestation record is a chain of certificates. The leaf certificate links to the public * key of this key pair and other properties of the key or the device. If the key is in secure * hardware, and if the secure hardware supports attestation, the leaf certificate will be * signed by a chain of certificates rooted at a trustworthy CA key. Otherwise the chain will be * rooted at an untrusted certificate. * * The attestation record could be for properties of the key, or include device identifiers. * * See {@link android.security.keystore.KeyGenParameterSpec.Builder#setAttestationChallenge} * and <a href="https://developer.android.com/training/articles/security-key-attestation.html"> * Key Attestation</a> for the format of the attestation record inside the certificate. */ public List<Certificate> getAttestationRecord() { if (mAttestationRecord == null) { return new ArrayList(); } return Arrays.asList(mAttestationRecord); } }
keystore/java/android/security/IKeyChainService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.security; import android.content.pm.StringParceledListSlice; import android.security.keystore.ParcelableKeyGenParameterSpec; /** * Caller is required to ensure that {@link KeyStore#unlock Loading @@ -31,6 +32,8 @@ interface IKeyChainService { boolean isUserSelectable(String alias); void setUserSelectable(String alias, boolean isUserSelectable); boolean generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec); // APIs used by CertInstaller and DevicePolicyManager String installCaCertificate(in byte[] caCertificate); Loading