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

Commit 6169239b authored by Eran Messeri's avatar Eran Messeri
Browse files

Utilize verbose KeyChain errors

As KeyChain reports detailed error codes about failure to generate keys
or attestation records for them, log these detailed errors and throw an
exception if the hardware does not support Device ID attestation.

Bug: 72642093
Bug: 73448533
Test: cts-tradefed run commandAndExit  cts-dev -s 127.0.0.1:50487 -a x86_64 -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement -l DEBUG
Change-Id: Ib12efcf48c158373e1fc28cc51d67e70282d029e
parent 3a5dabbb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4246,6 +4246,8 @@ public class DevicePolicyManager {
     *         algorithm specification in {@code keySpec} is not {@code RSAKeyGenParameterSpec}
     *         or {@code ECGenParameterSpec}, or if Device ID attestation was requested but the
     *         {@code keySpec} does not contain an attestation challenge.
     * @throws UnsupportedOperationException if Device ID attestation was requested but the
     *         underlying hardware does not support it.
     * @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
     */
    public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin,
+2 −2
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ interface IKeyChainService {
    boolean isUserSelectable(String alias);
    void setUserSelectable(String alias, boolean isUserSelectable);

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

+76 −0
Original line number Diff line number Diff line
@@ -245,6 +245,82 @@ public final class KeyChain {
     */
    public static final String EXTRA_KEY_ACCESSIBLE = "android.security.extra.KEY_ACCESSIBLE";

    /**
     * Indicates that a call to {@link #generateKeyPair} was successful.
     * @hide
     */
    public static final int KEY_GEN_SUCCESS = 0;

    /**
     * An alias was missing from the key specifications when calling {@link #generateKeyPair}.
     * @hide
     */
    public static final int KEY_GEN_MISSING_ALIAS = 1;

    /**
     * A key attestation challenge was provided to {@link #generateKeyPair}, but it shouldn't
     * have been provided.
     * @hide
     */
    public static final int KEY_GEN_SUPERFLUOUS_ATTESTATION_CHALLENGE = 2;

    /**
     * Algorithm not supported by {@link #generateKeyPair}
     * @hide
     */
    public static final int KEY_GEN_NO_SUCH_ALGORITHM = 3;

    /**
     * Invalid algorithm parameters when calling {@link #generateKeyPair}
     * @hide
     */
    public static final int KEY_GEN_INVALID_ALGORITHM_PARAMETERS = 4;

    /**
     * Keystore is not available when calling {@link #generateKeyPair}
     * @hide
     */
    public static final int KEY_GEN_NO_KEYSTORE_PROVIDER = 5;

    /**
     * General failure while calling {@link #generateKeyPair}
     * @hide
     */
    public static final int KEY_GEN_FAILURE = 6;

    /**
     * Successful call to {@link #attestKey}
     * @hide
     */
    public static final int KEY_ATTESTATION_SUCCESS = 0;

    /**
     * Attestation challenge missing when calling {@link #attestKey}
     * @hide
     */
    public static final int KEY_ATTESTATION_MISSING_CHALLENGE = 1;

    /**
     * The caller requested Device ID attestation when calling {@link #attestKey}, but has no
     * permissions to get device identifiers.
     * @hide
     */
    public static final int KEY_ATTESTATION_CANNOT_COLLECT_DATA = 2;

    /**
     * The underlying hardware does not support Device ID attestation or cannot attest to the
     * identifiers that are stored on the device. This indicates permanent inability
     * to get attestation records on the device.
     * @hide
     */
    public static final int KEY_ATTESTATION_CANNOT_ATTEST_IDS = 3;

    /**
     * General failure when calling {@link #attestKey}
     * @hide
     */
    public static final int KEY_ATTESTATION_FAILURE = 4;

    /**
     * Returns an {@code Intent} that can be used for credential
     * installation. The intent may be used without any extras, in
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ public class KeyStore {
    public static final int VALUE_CORRUPTED = 8;
    public static final int UNDEFINED_ACTION = 9;
    public static final int WRONG_PASSWORD = 10;
    public static final int CANNOT_ATTEST_IDS = -66;
    public static final int HARDWARE_TYPE_UNAVAILABLE = -68;

    /**
+12 −6
Original line number Diff line number Diff line
@@ -5533,10 +5533,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                        .setAttestationChallenge(null)
                        .build();
                final boolean generationResult = keyChain.generateKeyPair(algorithm,
                final int generationResult = keyChain.generateKeyPair(algorithm,
                    new ParcelableKeyGenParameterSpec(noAttestationSpec));
                if (!generationResult) {
                    Log.e(LOG_TAG, "KeyChain failed to generate a keypair.");
                if (generationResult != KeyChain.KEY_GEN_SUCCESS) {
                    Log.e(LOG_TAG, String.format(
                            "KeyChain failed to generate a keypair, error %d.", generationResult));
                    return false;
                }
@@ -5549,12 +5550,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                final byte[] attestationChallenge = keySpec.getAttestationChallenge();
                if (attestationChallenge != null) {
                    final boolean attestationResult = keyChain.attestKey(
                    final int attestationResult = keyChain.attestKey(
                            alias, attestationChallenge, attestationUtilsFlags, attestationChain);
                    if (!attestationResult) {
                    if (attestationResult != KeyChain.KEY_ATTESTATION_SUCCESS) {
                        Log.e(LOG_TAG, String.format(
                                "Attestation for %s failed, deleting key.", alias));
                                "Attestation for %s failed (rc=%d), deleting key.",
                                alias, attestationResult));
                        keyChain.removeKeyPair(alias);
                        if (attestationResult == KeyChain.KEY_ATTESTATION_CANNOT_ATTEST_IDS) {
                            throw new UnsupportedOperationException(
                                    "Device does not support Device ID attestation.");
                        }
                        return false;
                    }
                }