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

Commit b2795710 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "DevicePolicyManager: Add key generation functionality."

parents f20ed032 852c8f12
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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);
+50 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
+2 −0
Original line number Diff line number Diff line
@@ -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;

@@ -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);
+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);
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -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