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

Commit e239f782 authored by Alex Klyubin's avatar Alex Klyubin Committed by Android (Google) Code Review
Browse files

Merge "More Javadocs for AndroidKeyStore public classes." into mnc-dev

parents f8a96d16 eedda45a
Loading
Loading
Loading
Loading
+53 −13
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.security;

import android.app.KeyguardManager;
import android.content.Context;
import android.text.TextUtils;

@@ -24,19 +25,53 @@ import java.util.Date;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 * {@link AlgorithmParameterSpec} for initializing a {@code KeyGenerator} that works with
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>.
 *
 * <p>The Android KeyStore facility is accessed through a {@link KeyGenerator} API using the
 * {@code AndroidKeyStore} provider. The {@code context} passed in may be used to pop up some UI to
 * ask the user to unlock or initialize the Android KeyStore facility.
 *
 * <p>After generation, the {@code keyStoreAlias} is used with the
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
 * interface to retrieve the {@link SecretKey}.
 * {@link AlgorithmParameterSpec} for initializing a {@link KeyGenerator} of the
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
 * specifies whether user authentication is required for using the key, what uses the key is
 * authorized for (e.g., only in {@code CBC} mode), whether the key should be encrypted at rest, the
 * key's and validity start and end dates.
 *
 * <p>To generate a key, create an instance of this class using the {@link Builder}, initialize a
 * {@code KeyGenerator} of the desired key type (e.g., {@code AES} or {@code HmacSHA256}) from the
 * {@code AndroidKeyStore} provider with the {@code KeyGeneratorSpec} instance, and then generate a
 * key using {@link KeyGenerator#generateKey()}.
 *
 * <p>The generated key will be returned by the {@code KeyGenerator} and also stored in the Android
 * KeyStore under the alias specified in this {@code KeyGeneratorSpec}. To obtain the key from the
 * Android KeyStore use
 * {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)} or
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
 *
 * <p>NOTE: The key material of the keys generating using the {@code KeyGeneratorSpec} is not
 * accessible.
 *
 * <p><h3>Example</h3>
 * The following example illustrates how to generate an HMAC key in the Android KeyStore under alias
 * {@code key1} authorized to be used only for HMAC with SHA-256 digest and only if the user has
 * been authenticated within the last five minutes.
 * <pre> {@code
 * KeyGenerator keyGenerator = KeyGenerator.getInstance(
 *         KeyStoreKeyProperties.Algorithm.HMAC_SHA256,
 *         "AndroidKeyStore");
 * keyGenerator.initialize(
 *         new KeyGeneratorSpec.Builder(context)
 *                 .setAlias("key1")
 *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN
 *                         | KeyStoreKeyProperties.Purpose.VERIFY)
 *                 // Only permit this key to be used if the user authenticated
 *                 // within the last five minutes.
 *                 .setUserAuthenticationRequired(true)
 *                 .setUserAuthenticationValidityDurationSeconds(5 * 60)
 *                 .build());
 * SecretKey key = keyGenerator.generateKey();
 *
 * // The key can also be obtained from the Android KeyStore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * SecretKey key = (SecretKey) keyStore.getKey("key1", null);
 * }</pre>
 */
public class KeyGeneratorSpec implements AlgorithmParameterSpec {

@@ -207,7 +242,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
    }

    /**
     * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}.
     * Returns {@code true} if the key must be encrypted at rest. This will protect the key with the
     * secure lock screen credential (e.g., password, PIN, or pattern).
     */
    public boolean isEncryptionRequired() {
        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
@@ -266,9 +302,13 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
        }

        /**
         * Indicates that this key must be encrypted at rest on storage. Note that enabling this
         * will require that the user enable a strong lock screen (e.g., PIN, password) before
         * creating or using the generated key is successful.
         * Indicates that this key must be encrypted at rest. This will protect the key with the
         * secure lock screen credential (e.g., password, PIN, or pattern).
         *
         * <p>Note that this feature requires that the secure lock screen (e.g., password, PIN,
         * pattern) is set up. Otherwise key generation will fail.
         *
         * @see KeyguardManager#isDeviceSecure()
         */
        public Builder setEncryptionRequired(boolean required) {
            if (required) {
+75 −26
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package android.security;

import android.app.KeyguardManager;
import android.content.Context;
import android.text.TextUtils;

import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
@@ -29,26 +31,64 @@ import java.util.Date;
import javax.security.auth.x500.X500Principal;

/**
 * This provides the required parameters needed for initializing the
 * {@code KeyPairGenerator} that works with
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore
 * facility</a>. The Android KeyStore facility is accessed through a
 * {@link java.security.KeyPairGenerator} API using the {@code AndroidKeyStore}
 * provider. The {@code context} passed in may be used to pop up some UI to ask
 * the user to unlock or initialize the Android KeyStore facility.
 * <p>
 * After generation, the {@code keyStoreAlias} is used with the
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
 * interface to retrieve the {@link PrivateKey} and its associated
 * {@link Certificate} chain.
 * <p>
 * The KeyPair generator will create a self-signed certificate with the subject
 * as its X.509v3 Subject Distinguished Name and as its X.509v3 Issuer
 * Distinguished Name along with the other parameters specified with the
 * {@link Builder}.
 * <p>
 * The self-signed X.509 certificate may be replaced at a later time by a
 * certificate signed by a real Certificate Authority.
 * {@link AlgorithmParameterSpec} for initializing a {@link KeyPairGenerator} of the
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
 * specifies whether user authentication is required for using the private key, what uses the
 * private key is authorized for (e.g., only for signing -- decryption not permitted), whether the
 * private key should be encrypted at rest, the private key's and validity start and end dates.
 *
 * <p>To generate a key pair, create an instance of this class using the {@link Builder}, initialize
 * a {@code KeyPairGenerator} of the desired key type (e.g., {@code EC} or {@code RSA}) from the
 * {@code AndroidKeyStore} provider with the {@code KeyPairGeneratorSpec} instance, and then
 * generate a key pair using {@link KeyPairGenerator#generateKeyPair()}.
 *
 * <p>The generated key pair will be returned by the {@code KeyPairGenerator} and also stored in the
 * Android KeyStore under the alias specified in this {@code KeyPairGeneratorSpec}. To obtain the
 * private key from the Android KeyStore use
 * {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)} or
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
 * To obtain the public key from the Android KeyStore use
 * {@link java.security.KeyStore#getCertificate(String)} and then
 * {@link Certificate#getPublicKey()}.
 *
 * <p>A self-signed X.509 certificate will be also generated and stored in the Android KeyStore.
 * This is because the {@link java.security.KeyStore} abstraction does not support storing key pairs
 * without a certificate. The subject, serial number, and validity dates of the certificate can be
 * specified in this {@code KeyPairGeneratorSpec}. The self-signed certificate may be replaced at a
 * later time by a certificate signed by a Certificate Authority (CA).
 *
 * <p>NOTE: The key material of the private keys generating using the {@code KeyPairGeneratorSpec}
 * is not accessible. The key material of the public keys is accessible.
 *
 * <p><h3>Example</h3>
 * The following example illustrates how to generate an EC key pair in the Android KeyStore under
 * alias {@code key2} authorized to be used only for signing using SHA-256, SHA-384, or SHA-512
 * digest and only if the user has been authenticated within the last five minutes.
 * <pre> {@code
 * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
 *         KeyStoreKeyProperties.Algorithm.EC,
 *         "AndroidKeyStore");
 * keyPairGenerator.initialize(
 *         new KeyGeneratorSpec.Builder(context)
 *                 .setAlias("key2")
 *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN
 *                         | KeyStoreKeyProperties.Purpose.VERIFY)
 *                 .setDigests(KeyStoreKeyProperties.Digest.SHA256
 *                         | KeyStoreKeyProperties.Digest.SHA384
 *                         | KeyStoreKeyProperties.Digest.SHA512)
 *                 // Only permit this key to be used if the user authenticated
 *                 // within the last five minutes.
 *                 .setUserAuthenticationRequired(true)
 *                 .setUserAuthenticationValidityDurationSeconds(5 * 60)
 *                 .build());
 * KeyPair keyPair = keyPairGenerator.generateKey();
 *
 * // The key pair can also be obtained from the Android KeyStore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * PrivateKey privateKey = (PrivateKey) keyStore.getKey("key2", null);
 * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 * }</pre>
 */
public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {

@@ -307,8 +347,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
    }

    /**
     * Returns {@code true} if this parameter will require generated keys to be
     * encrypted in the {@link java.security.KeyStore}.
     * Returns {@code true} if the key must be encrypted at rest. This will protect the key pair
     * with the secure lock screen credential (e.g., password, PIN, or pattern).
     */
    public boolean isEncryptionRequired() {
        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
@@ -614,10 +654,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
        }

        /**
         * Indicates that this key must be encrypted at rest on storage. Note
         * that enabling this will require that the user enable a strong lock
         * screen (e.g., PIN, password) before creating or using the generated
         * key is successful.
         * Indicates that this key must be encrypted at rest. This will protect the key pair with
         * the secure lock screen credential (e.g., password, PIN, or pattern).
         *
         * <p>Note that this feature requires that the secure lock screen (e.g., password, PIN,
         * pattern) is set up. Otherwise key pair generation will fail.
         *
         * @see KeyguardManager#isDeviceSecure()
         */
        public Builder setEncryptionRequired() {
            mFlags |= KeyStore.FLAG_ENCRYPTED;
@@ -689,6 +732,12 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
         *
         * <p>This must be specified for all keys. There is no default.
         *
         * <p>If the set of purposes for which the key can be used does not contain
         * {@link KeyStoreKeyProperties.Purpose#SIGN}, the self-signed certificate generated by
         * {@link KeyPairGenerator} of {@code AndroidKeyStore} provider will contain an invalid
         * signature. This is OK if the certificate is only used for obtaining the public key from
         * Android KeyStore.
         *
         * <p><b>NOTE: This has currently no effect.
         */
        public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
+38 −1
Original line number Diff line number Diff line
@@ -16,12 +16,49 @@

package android.security;

import java.security.PrivateKey;
import java.security.spec.KeySpec;
import java.util.Date;

import javax.crypto.SecretKey;

/**
 * Information about a key from the <a href="{@docRoot}training/articles/keystore.html">Android
 * KeyStore</a>.
 * KeyStore</a>. This class describes whether the key material is available in
 * plaintext outside of secure hardware, whether user authentication is required for using the key
 * and whether this requirement is enforced by secure hardware, the key's origin, what uses the key
 * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be
 * encrypted at rest, the key's and validity start and end dates.
 *
 * <p><h3>Example: Symmetric Key</h3>
 * The following example illustrates how to obtain a {@link KeyStoreKeySpec} describing the provided
 * Android KeyStore {@link SecretKey}.
 * <pre> {@code
 * SecretKey key = ...; // Android KeyStore key
 *
 * SecretKeyFactory factory = SecretKeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
 * KeyStoreKeySpec spec;
 * try &#123;
 *     spec = (KeyStoreKeySpec) factory.getKeySpec(key, KeyStoreKeySpec.class);
 * &#125; catch (InvalidKeySpecException e) &#123;
 *     // Not an Android KeyStore key.
 * &#125;
 * }</pre>
 *
 * <p><h3>Example: Private Key</h3>
 * The following example illustrates how to obtain a {@link KeyStoreKeySpec} describing the provided
 * Android KeyStore {@link PrivateKey}.
 * <pre> {@code
 * PrivateKey key = ...; // Android KeyStore key
 *
 * KeyFactory factory = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
 * KeyStoreKeySpec spec;
 * try &#123;
 *     spec = factory.getKeySpec(key, KeyStoreKeySpec.class);
 * &#125; catch (InvalidKeySpecException e) &#123;
 *     // Not an Android KeyStore key.
 * &#125;
 * }</pre>
 */
public class KeyStoreKeySpec implements KeySpec {
    private final String mKeystoreAlias;
+85 −18
Original line number Diff line number Diff line
@@ -16,27 +16,89 @@

package android.security;

import android.app.KeyguardManager;
import android.content.Context;

import java.security.Key;
import java.security.KeyStore.ProtectionParameter;
import java.security.cert.Certificate;
import java.util.Date;

import javax.crypto.Cipher;

/**
 * Parameters specifying how to secure and restrict the use of a key being
 * imported into the
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore
 * facility</a>. The Android KeyStore facility is accessed through a
 * {@link java.security.KeyStore} API using the {@code AndroidKeyStore}
 * provider. The {@code context} passed in may be used to pop up some UI to ask
 * the user to unlock or initialize the Android KeyStore facility.
 * <p>
 * Any entries placed in the {@code KeyStore} may be retrieved later. Note that
 * there is only one logical instance of the {@code KeyStore} per application
 * UID so apps using the {@code sharedUid} facility will also share a
 * {@code KeyStore}.
 * Parameters specifying how to secure and restrict the use of a key or key pair being imported into
 * the <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
 * specifies whether user authentication is required for using the key, what uses the key is
 * authorized for (e.g., only in {@code CTR} mode, or only for signing -- decryption not permitted),
 * whether the key should be encrypted at rest, the key's and validity start and end dates.
 *
 * <p>To import a key or key pair into the Android KeyStore, create an instance of this class using
 * the {@link Builder} and pass the instance into {@link java.security.KeyStore#setEntry(String, java.security.KeyStore.Entry, ProtectionParameter) KeyStore.setEntry}
 * with the key or key pair being imported.
 *
 * <p>To obtain the secret/symmetric or private key from the Android KeyStore use
 * {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)} or
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
 * To obtain the public key from the Android KeyStore use
 * {@link java.security.KeyStore#getCertificate(String)} and then
 * {@link Certificate#getPublicKey()}.
 *
 * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible.
 *
 * <p><h3>Example: Symmetric Key</h3>
 * The following example illustrates how to import an AES key into the Android KeyStore under alias
 * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
 * padding. The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
 * <pre> {@code
 * SecretKey key = ...; // AES key
 *
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * keyStore.setEntry(
 *         "key1",
 *         new KeyStore.SecretKeyEntry(key),
 *         new KeyStoreParameter.Builder(context)
 *                 .setPurposes(KeyStoreKeyProperties.Purpose.ENCRYPT
 *                         | KeyStoreKeyProperties.Purpose.DECRYPT)
 *                 .setBlockMode(KeyStoreKeyProperties.BlockMode.CBC)
 *                 .setEncryptionPaddings(
 *                         KeyStoreKeyProperties.EncryptionPaddings.PKCS7)
 *                 .build());
 * // Key imported, obtain a reference to it.
 * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 * // The original key can now be thrown away.
 * }</pre>
 *
 * <p><h3>Example: Asymmetric Key Pair</h3>
 * The following example illustrates how to import an EC key pair into the Android KeyStore under
 * alias {@code key2} authorized to be used only for signing with SHA-256 digest and only if
 * the user has been authenticated within the last ten minutes. Both the private and the public key
 * must export their key material via {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509}
 * format respectively.
 * <pre> {@code
 * PrivateKey privateKey = ...;   // EC private key
 * Certificate[] certChain = ...; // Certificate chain with the first certificate
 *                                // containing the corresponding EC public key.
 *
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * keyStore.setEntry(
 *         "key2",
 *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
 *         new KeyStoreParameter.Builder(context)
 *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN)
 *                 .setDigests(KeyStoreKeyProperties.Digest.SHA256)
 *                 // Only permit this key to be used if the user
 *                 // authenticated within the last ten minutes.
 *                 .setUserAuthenticationRequired(true)
 *                 .setUserAuthenticationValidityDurationSeconds(10 * 60)
 *                 .build());
 * // Key pair imported, obtain a reference to it.
 * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 * // The original private key can now be thrown away.
 * }</pre>
 */
public final class KeyStoreParameter implements ProtectionParameter {
    private final Context mContext;
@@ -107,8 +169,9 @@ public final class KeyStoreParameter implements ProtectionParameter {
    }

    /**
     * Returns {@code true} if this parameter requires entries to be encrypted
     * on the disk.
     * Returns {@code true} if the {@link java.security.KeyStore} entry must be encrypted at rest.
     * This will protect the entry with the secure lock screen credential (e.g., password, PIN, or
     * pattern).
     */
    public boolean isEncryptionRequired() {
        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
@@ -275,10 +338,14 @@ public final class KeyStoreParameter implements ProtectionParameter {
        }

        /**
         * Indicates that this key must be encrypted at rest on storage. Note
         * that enabling this will require that the user enable a strong lock
         * screen (e.g., PIN, password) before creating or using the generated
         * key is successful.
         * Indicates that this {@link java.security.KeyStore} entry must be encrypted at rest. This
         * will protect the entry with the secure lock screen credential (e.g., password, PIN, or
         * pattern).
         *
         * <p>Note that enabling this feature requires that the secure lock screen (e.g., password,
         * PIN, pattern) is set up. Otherwise setting the {@code KeyStore} entry will fail.
         *
         * @see KeyguardManager#isDeviceSecure()
         */
        public Builder setEncryptionRequired(boolean required) {
            if (required) {