1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.security.keystore;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21
22import java.security.PrivateKey;
23import java.security.spec.KeySpec;
24import java.util.Date;
25
26import javax.crypto.SecretKey;
27
28/**
29 * Information about a key from the <a href="{@docRoot}training/articles/keystore.html">Android
30 * Keystore system</a>. This class describes whether the key material is available in
31 * plaintext outside of secure hardware, whether user authentication is required for using the key
32 * and whether this requirement is enforced by secure hardware, the key's origin, what uses the key
33 * is authorized for (e.g., only in {@code GCM} mode, or signing only), whether the key should be
34 * encrypted at rest, the key's and validity start and end dates.
35 *
36 * <p>Instances of this class are immutable.
37 *
38 * <p><h3>Example: Symmetric Key</h3>
39 * The following example illustrates how to obtain a {@code KeyInfo} describing the provided Android
40 * Keystore {@link SecretKey}.
41 * <pre> {@code
42 * SecretKey key = ...; // Android Keystore key
43 *
44 * SecretKeyFactory factory = SecretKeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
45 * KeyInfo keyInfo;
46 * try &#123;
47 *     keyInfo = (KeyInfo) factory.getKeySpec(key, KeyInfo.class);
48 * &#125; catch (InvalidKeySpecException e) &#123;
49 *     // Not an Android KeyStore key.
50 * &#125;
51 * }</pre>
52 *
53 * <p><h3>Example: Private Key</h3>
54 * The following example illustrates how to obtain a {@code KeyInfo} describing the provided
55 * Android KeyStore {@link PrivateKey}.
56 * <pre> {@code
57 * PrivateKey key = ...; // Android KeyStore key
58 *
59 * KeyFactory factory = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
60 * KeyInfo keyInfo;
61 * try &#123;
62 *     keyInfo = factory.getKeySpec(key, KeyInfo.class);
63 * &#125; catch (InvalidKeySpecException e) &#123;
64 *     // Not an Android KeyStore key.
65 * &#125;
66 * }</pre>
67 */
68public class KeyInfo implements KeySpec {
69    private final String mKeystoreAlias;
70    private final int mKeySize;
71    private final boolean mInsideSecureHardware;
72    private final @KeyProperties.OriginEnum int mOrigin;
73    private final Date mKeyValidityStart;
74    private final Date mKeyValidityForOriginationEnd;
75    private final Date mKeyValidityForConsumptionEnd;
76    private final @KeyProperties.PurposeEnum int mPurposes;
77    private final @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
78    private final @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
79    private final @KeyProperties.DigestEnum String[] mDigests;
80    private final @KeyProperties.BlockModeEnum String[] mBlockModes;
81    private final boolean mUserAuthenticationRequired;
82    private final int mUserAuthenticationValidityDurationSeconds;
83    private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
84
85    /**
86     * @hide
87     */
88    public KeyInfo(String keystoreKeyAlias,
89            boolean insideSecureHardware,
90            @KeyProperties.OriginEnum int origin,
91            int keySize,
92            Date keyValidityStart,
93            Date keyValidityForOriginationEnd,
94            Date keyValidityForConsumptionEnd,
95            @KeyProperties.PurposeEnum int purposes,
96            @KeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
97            @KeyProperties.SignaturePaddingEnum String[] signaturePaddings,
98            @KeyProperties.DigestEnum String[] digests,
99            @KeyProperties.BlockModeEnum String[] blockModes,
100            boolean userAuthenticationRequired,
101            int userAuthenticationValidityDurationSeconds,
102            boolean userAuthenticationRequirementEnforcedBySecureHardware) {
103        mKeystoreAlias = keystoreKeyAlias;
104        mInsideSecureHardware = insideSecureHardware;
105        mOrigin = origin;
106        mKeySize = keySize;
107        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
108        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
109        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
110        mPurposes = purposes;
111        mEncryptionPaddings =
112                ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
113        mSignaturePaddings =
114                ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
115        mDigests = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(digests));
116        mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
117        mUserAuthenticationRequired = userAuthenticationRequired;
118        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
119        mUserAuthenticationRequirementEnforcedBySecureHardware =
120                userAuthenticationRequirementEnforcedBySecureHardware;
121    }
122
123    /**
124     * Gets the entry alias under which the key is stored in the {@code AndroidKeyStore}.
125     */
126    public String getKeystoreAlias() {
127        return mKeystoreAlias;
128    }
129
130    /**
131     * Returns {@code true} if the key resides inside secure hardware (e.g., Trusted Execution
132     * Environment (TEE) or Secure Element (SE)). Key material of such keys is available in
133     * plaintext only inside the secure hardware and is not exposed outside of it.
134     */
135    public boolean isInsideSecureHardware() {
136        return mInsideSecureHardware;
137    }
138
139    /**
140     * Gets the origin of the key. See {@link KeyProperties}.{@code ORIGIN} constants.
141     */
142    public @KeyProperties.OriginEnum int getOrigin() {
143        return mOrigin;
144    }
145
146    /**
147     * Gets the size of the key in bits.
148     */
149    public int getKeySize() {
150        return mKeySize;
151    }
152
153    /**
154     * Gets the time instant before which the key is not yet valid.
155     *
156     * @return instant or {@code null} if not restricted.
157     */
158    @Nullable
159    public Date getKeyValidityStart() {
160        return Utils.cloneIfNotNull(mKeyValidityStart);
161    }
162
163    /**
164     * Gets the time instant after which the key is no long valid for decryption and verification.
165     *
166     * @return instant or {@code null} if not restricted.
167     */
168    @Nullable
169    public Date getKeyValidityForConsumptionEnd() {
170        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
171    }
172
173    /**
174     * Gets the time instant after which the key is no long valid for encryption and signing.
175     *
176     * @return instant or {@code null} if not restricted.
177     */
178    @Nullable
179    public Date getKeyValidityForOriginationEnd() {
180        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
181    }
182
183    /**
184     * Gets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
185     * Attempts to use the key for any other purpose will be rejected.
186     *
187     * <p>See {@link KeyProperties}.{@code PURPOSE} flags.
188     */
189    public @KeyProperties.PurposeEnum int getPurposes() {
190        return mPurposes;
191    }
192
193    /**
194     * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
195     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
196     * rejected.
197     *
198     * <p>See {@link KeyProperties}.{@code BLOCK_MODE} constants.
199     */
200    @NonNull
201    public @KeyProperties.BlockModeEnum String[] getBlockModes() {
202        return ArrayUtils.cloneIfNotEmpty(mBlockModes);
203    }
204
205    /**
206     * Gets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code PKCS1Padding},
207     * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to use
208     * the key with any other padding scheme will be rejected.
209     *
210     * <p>See {@link KeyProperties}.{@code ENCRYPTION_PADDING} constants.
211     */
212    @NonNull
213    public @KeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
214        return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings);
215    }
216
217    /**
218     * Gets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
219     * can be used when signing/verifying. Attempts to use the key with any other padding scheme
220     * will be rejected.
221     *
222     * <p>See {@link KeyProperties}.{@code SIGNATURE_PADDING} constants.
223     */
224    @NonNull
225    public @KeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
226        return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings);
227    }
228
229    /**
230     * Gets the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384}) with which the key
231     * can be used.
232     *
233     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
234     */
235    @NonNull
236    public @KeyProperties.DigestEnum String[] getDigests() {
237        return ArrayUtils.cloneIfNotEmpty(mDigests);
238    }
239
240    /**
241     * Returns {@code true} if the key is authorized to be used only if the user has been
242     * authenticated.
243     *
244     * <p>This authorization applies only to secret key and private key operations. Public key
245     * operations are not restricted.
246     *
247     * @see #getUserAuthenticationValidityDurationSeconds()
248     * @see KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)
249     * @see KeyProtection.Builder#setUserAuthenticationRequired(boolean)
250     */
251    public boolean isUserAuthenticationRequired() {
252        return mUserAuthenticationRequired;
253    }
254
255    /**
256     * Gets the duration of time (seconds) for which this key is authorized to be used after the
257     * user is successfully authenticated. This has effect only if user authentication is required
258     * (see {@link #isUserAuthenticationRequired()}).
259     *
260     * <p>This authorization applies only to secret key and private key operations. Public key
261     * operations are not restricted.
262     *
263     * @return duration in seconds or {@code -1} if authentication is required for every use of the
264     *         key.
265     *
266     * @see #isUserAuthenticationRequired()
267     */
268    public int getUserAuthenticationValidityDurationSeconds() {
269        return mUserAuthenticationValidityDurationSeconds;
270    }
271
272    /**
273     * Returns {@code true} if the requirement that this key can only be used if the user has been
274     * authenticated if enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
275     * Secure Element (SE)).
276     *
277     * @see #isUserAuthenticationRequired()
278     */
279    public boolean isUserAuthenticationRequirementEnforcedBySecureHardware() {
280        return mUserAuthenticationRequirementEnforcedBySecureHardware;
281    }
282}
283