1 /*
2  * Copyright (C) 2012 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 
17 package android.security;
18 
19 import android.app.KeyguardManager;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Context;
23 import android.security.keystore.KeyGenParameterSpec;
24 import android.security.keystore.KeyProperties;
25 import android.text.TextUtils;
26 
27 import java.math.BigInteger;
28 import java.security.NoSuchAlgorithmException;
29 import java.security.PrivateKey;
30 import java.security.cert.Certificate;
31 import java.security.spec.AlgorithmParameterSpec;
32 import java.util.Date;
33 
34 import javax.security.auth.x500.X500Principal;
35 
36 /**
37  * This provides the required parameters needed for initializing the
38  * {@code KeyPairGenerator} that works with
39  * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore
40  * facility</a>. The Android KeyStore facility is accessed through a
41  * {@link java.security.KeyPairGenerator} API using the {@code AndroidKeyStore}
42  * provider. The {@code context} passed in may be used to pop up some UI to ask
43  * the user to unlock or initialize the Android KeyStore facility.
44  * <p>
45  * After generation, the {@code keyStoreAlias} is used with the
46  * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
47  * interface to retrieve the {@link PrivateKey} and its associated
48  * {@link Certificate} chain.
49  * <p>
50  * The KeyPair generator will create a self-signed certificate with the subject
51  * as its X.509v3 Subject Distinguished Name and as its X.509v3 Issuer
52  * Distinguished Name along with the other parameters specified with the
53  * {@link Builder}.
54  * <p>
55  * The self-signed X.509 certificate may be replaced at a later time by a
56  * certificate signed by a real Certificate Authority.
57  *
58  * @deprecated Use {@link KeyGenParameterSpec} instead.
59  */
60 @Deprecated
61 public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
62 
63     private final Context mContext;
64 
65     private final String mKeystoreAlias;
66 
67     private final String mKeyType;
68 
69     private final int mKeySize;
70 
71     private final AlgorithmParameterSpec mSpec;
72 
73     private final X500Principal mSubjectDN;
74 
75     private final BigInteger mSerialNumber;
76 
77     private final Date mStartDate;
78 
79     private final Date mEndDate;
80 
81     private final int mFlags;
82 
83     /**
84      * Parameter specification for the "{@code AndroidKeyPairGenerator}"
85      * instance of the {@link java.security.KeyPairGenerator} API. The
86      * {@code context} passed in may be used to pop up some UI to ask the user
87      * to unlock or initialize the Android keystore facility.
88      * <p>
89      * After generation, the {@code keyStoreAlias} is used with the
90      * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
91      * interface to retrieve the {@link PrivateKey} and its associated
92      * {@link Certificate} chain.
93      * <p>
94      * The KeyPair generator will create a self-signed certificate with the
95      * properties of {@code subjectDN} as its X.509v3 Subject Distinguished Name
96      * and as its X.509v3 Issuer Distinguished Name, using the specified
97      * {@code serialNumber}, and the validity date starting at {@code startDate}
98      * and ending at {@code endDate}.
99      *
100      * @param context Android context for the activity
101      * @param keyStoreAlias name to use for the generated key in the Android
102      *            keystore
103      * @param keyType key algorithm to use (RSA, DSA, EC)
104      * @param keySize size of key to generate
105      * @param spec the underlying key type parameters
106      * @param subjectDN X.509 v3 Subject Distinguished Name
107      * @param serialNumber X509 v3 certificate serial number
108      * @param startDate the start of the self-signed certificate validity period
109      * @param endDate the end date of the self-signed certificate validity
110      *            period
111      * @throws IllegalArgumentException when any argument is {@code null} or
112      *             {@code endDate} is before {@code startDate}.
113      * @hide should be built with KeyPairGeneratorSpecBuilder
114      */
KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize, AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags)115     public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize,
116             AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber,
117             Date startDate, Date endDate, int flags) {
118         if (context == null) {
119             throw new IllegalArgumentException("context == null");
120         } else if (TextUtils.isEmpty(keyStoreAlias)) {
121             throw new IllegalArgumentException("keyStoreAlias must not be empty");
122         } else if (subjectDN == null) {
123             throw new IllegalArgumentException("subjectDN == null");
124         } else if (serialNumber == null) {
125             throw new IllegalArgumentException("serialNumber == null");
126         } else if (startDate == null) {
127             throw new IllegalArgumentException("startDate == null");
128         } else if (endDate == null) {
129             throw new IllegalArgumentException("endDate == null");
130         } else if (endDate.before(startDate)) {
131             throw new IllegalArgumentException("endDate < startDate");
132         }
133 
134         if (endDate.before(startDate)) {
135             throw new IllegalArgumentException("endDate < startDate");
136         }
137 
138         mContext = context;
139         mKeystoreAlias = keyStoreAlias;
140         mKeyType = keyType;
141         mKeySize = keySize;
142         mSpec = spec;
143         mSubjectDN = subjectDN;
144         mSerialNumber = serialNumber;
145         mStartDate = startDate;
146         mEndDate = endDate;
147         mFlags = flags;
148     }
149 
150     /**
151      * Gets the Android context used for operations with this instance.
152      */
getContext()153     public Context getContext() {
154         return mContext;
155     }
156 
157     /**
158      * Returns the alias that will be used in the {@code java.security.KeyStore}
159      * in conjunction with the {@code AndroidKeyStore}.
160      */
getKeystoreAlias()161     public String getKeystoreAlias() {
162         return mKeystoreAlias;
163     }
164 
165     /**
166      * Returns the type of key pair (e.g., {@code EC}, {@code RSA}) to be generated. See
167      * {@link KeyProperties}.{@code KEY_ALGORITHM} constants.
168      */
169     @Nullable
getKeyType()170     public @KeyProperties.KeyAlgorithmEnum String getKeyType() {
171         return mKeyType;
172     }
173 
174     /**
175      * Returns the key size specified by this parameter. For instance, for RSA
176      * this will return the modulus size and for EC it will return the field
177      * size.
178      */
getKeySize()179     public int getKeySize() {
180         return mKeySize;
181     }
182 
183     /**
184      * Returns the {@link AlgorithmParameterSpec} that will be used for creation
185      * of the key pair.
186      */
187     @NonNull
getAlgorithmParameterSpec()188     public AlgorithmParameterSpec getAlgorithmParameterSpec() {
189         return mSpec;
190     }
191 
192     /**
193      * Gets the subject distinguished name to be used on the X.509 certificate
194      * that will be put in the {@link java.security.KeyStore}.
195      */
196     @NonNull
getSubjectDN()197     public X500Principal getSubjectDN() {
198         return mSubjectDN;
199     }
200 
201     /**
202      * Gets the serial number to be used on the X.509 certificate that will be
203      * put in the {@link java.security.KeyStore}.
204      */
205     @NonNull
getSerialNumber()206     public BigInteger getSerialNumber() {
207         return mSerialNumber;
208     }
209 
210     /**
211      * Gets the start date to be used on the X.509 certificate that will be put
212      * in the {@link java.security.KeyStore}.
213      */
214     @NonNull
getStartDate()215     public Date getStartDate() {
216         return mStartDate;
217     }
218 
219     /**
220      * Gets the end date to be used on the X.509 certificate that will be put in
221      * the {@link java.security.KeyStore}.
222      */
223     @NonNull
getEndDate()224     public Date getEndDate() {
225         return mEndDate;
226     }
227 
228     /**
229      * @hide
230      */
getFlags()231     public int getFlags() {
232         return mFlags;
233     }
234 
235     /**
236      * Returns {@code true} if the key must be encrypted at rest. This will protect the key pair
237      * with the secure lock screen credential (e.g., password, PIN, or pattern).
238      *
239      * <p>Note that encrypting the key at rest requires that the secure lock screen (e.g., password,
240      * PIN, pattern) is set up, otherwise key generation will fail. Moreover, this key will be
241      * deleted when the secure lock screen is disabled or reset (e.g., by the user or a Device
242      * Administrator). Finally, this key cannot be used until the user unlocks the secure lock
243      * screen after boot.
244      *
245      * @see KeyguardManager#isDeviceSecure()
246      */
isEncryptionRequired()247     public boolean isEncryptionRequired() {
248         return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
249     }
250 
251     /**
252      * Builder class for {@link KeyPairGeneratorSpec} objects.
253      * <p>
254      * This will build a parameter spec for use with the
255      * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore
256      * facility</a>.
257      * <p>
258      * The required fields must be filled in with the builder.
259      * <p>
260      * Example:
261      *
262      * <pre class="prettyprint">
263      * Calendar start = Calendar.getInstance();
264      * Calendar end = Calendar.getInstance();
265      * end.add(Calendar.YEAR, 1);
266      *
267      * KeyPairGeneratorSpec spec =
268      *         new KeyPairGeneratorSpec.Builder(mContext).setAlias(&quot;myKey&quot;)
269      *                 .setSubject(new X500Principal(&quot;CN=myKey&quot;)).setSerialNumber(BigInteger.valueOf(1337))
270      *                 .setStartDate(start.getTime()).setEndDate(end.getTime()).build();
271      * </pre>
272      *
273      *  @deprecated Use {@link KeyGenParameterSpec.Builder} instead.
274      */
275     @Deprecated
276     public final static class Builder {
277         private final Context mContext;
278 
279         private String mKeystoreAlias;
280 
281         private String mKeyType;
282 
283         private int mKeySize = -1;
284 
285         private AlgorithmParameterSpec mSpec;
286 
287         private X500Principal mSubjectDN;
288 
289         private BigInteger mSerialNumber;
290 
291         private Date mStartDate;
292 
293         private Date mEndDate;
294 
295         private int mFlags;
296 
297         /**
298          * Creates a new instance of the {@code Builder} with the given
299          * {@code context}. The {@code context} passed in may be used to pop up
300          * some UI to ask the user to unlock or initialize the Android KeyStore
301          * facility.
302          */
Builder(@onNull Context context)303         public Builder(@NonNull Context context) {
304             if (context == null) {
305                 throw new NullPointerException("context == null");
306             }
307             mContext = context;
308         }
309 
310         /**
311          * Sets the alias to be used to retrieve the key later from a
312          * {@link java.security.KeyStore} instance using the
313          * {@code AndroidKeyStore} provider.
314          */
315         @NonNull
setAlias(@onNull String alias)316         public Builder setAlias(@NonNull String alias) {
317             if (alias == null) {
318                 throw new NullPointerException("alias == null");
319             }
320             mKeystoreAlias = alias;
321             return this;
322         }
323 
324         /**
325          * Sets the type of key pair (e.g., {@code EC}, {@code RSA}) of the key pair to be
326          * generated. See {@link KeyProperties}.{@code KEY_ALGORITHM} constants.
327          *
328          */
329         @NonNull
setKeyType(@onNull @eyProperties.KeyAlgorithmEnum String keyType)330         public Builder setKeyType(@NonNull @KeyProperties.KeyAlgorithmEnum String keyType)
331                 throws NoSuchAlgorithmException {
332             if (keyType == null) {
333                 throw new NullPointerException("keyType == null");
334             } else {
335                 try {
336                     KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(keyType);
337                 } catch (IllegalArgumentException e) {
338                     throw new NoSuchAlgorithmException("Unsupported key type: " + keyType);
339                 }
340             }
341             mKeyType = keyType;
342             return this;
343         }
344 
345         /**
346          * Sets the key size for the keypair to be created. For instance, for a
347          * key type of RSA this will set the modulus size and for a key type of
348          * EC it will select a curve with a matching field size.
349          */
350         @NonNull
setKeySize(int keySize)351         public Builder setKeySize(int keySize) {
352             if (keySize < 0) {
353                 throw new IllegalArgumentException("keySize < 0");
354             }
355             mKeySize = keySize;
356             return this;
357         }
358 
359         /**
360          * Sets the algorithm-specific key generation parameters. For example, for RSA keys
361          * this may be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}.
362          */
setAlgorithmParameterSpec(@onNull AlgorithmParameterSpec spec)363         public Builder setAlgorithmParameterSpec(@NonNull AlgorithmParameterSpec spec) {
364             if (spec == null) {
365                 throw new NullPointerException("spec == null");
366             }
367             mSpec = spec;
368             return this;
369         }
370 
371         /**
372          * Sets the subject used for the self-signed certificate of the
373          * generated key pair.
374          */
375         @NonNull
setSubject(@onNull X500Principal subject)376         public Builder setSubject(@NonNull X500Principal subject) {
377             if (subject == null) {
378                 throw new NullPointerException("subject == null");
379             }
380             mSubjectDN = subject;
381             return this;
382         }
383 
384         /**
385          * Sets the serial number used for the self-signed certificate of the
386          * generated key pair.
387          */
388         @NonNull
setSerialNumber(@onNull BigInteger serialNumber)389         public Builder setSerialNumber(@NonNull BigInteger serialNumber) {
390             if (serialNumber == null) {
391                 throw new NullPointerException("serialNumber == null");
392             }
393             mSerialNumber = serialNumber;
394             return this;
395         }
396 
397         /**
398          * Sets the start of the validity period for the self-signed certificate
399          * of the generated key pair.
400          */
401         @NonNull
setStartDate(@onNull Date startDate)402         public Builder setStartDate(@NonNull Date startDate) {
403             if (startDate == null) {
404                 throw new NullPointerException("startDate == null");
405             }
406             mStartDate = startDate;
407             return this;
408         }
409 
410         /**
411          * Sets the end of the validity period for the self-signed certificate
412          * of the generated key pair.
413          */
414         @NonNull
setEndDate(@onNull Date endDate)415         public Builder setEndDate(@NonNull Date endDate) {
416             if (endDate == null) {
417                 throw new NullPointerException("endDate == null");
418             }
419             mEndDate = endDate;
420             return this;
421         }
422 
423         /**
424          * Indicates that this key pair must be encrypted at rest. This will protect the key pair
425          * with the secure lock screen credential (e.g., password, PIN, or pattern).
426          *
427          * <p>Note that this feature requires that the secure lock screen (e.g., password, PIN,
428          * pattern) is set up, otherwise key pair generation will fail. Moreover, this key pair will
429          * be deleted when the secure lock screen is disabled or reset (e.g., by the user or a
430          * Device Administrator). Finally, this key pair cannot be used until the user unlocks the
431          * secure lock screen after boot.
432          *
433          * @see KeyguardManager#isDeviceSecure()
434          */
435         @NonNull
setEncryptionRequired()436         public Builder setEncryptionRequired() {
437             mFlags |= KeyStore.FLAG_ENCRYPTED;
438             return this;
439         }
440 
441         /**
442          * Builds the instance of the {@code KeyPairGeneratorSpec}.
443          *
444          * @throws IllegalArgumentException if a required field is missing
445          * @return built instance of {@code KeyPairGeneratorSpec}
446          */
447         @NonNull
build()448         public KeyPairGeneratorSpec build() {
449             return new KeyPairGeneratorSpec(mContext,
450                     mKeystoreAlias,
451                     mKeyType,
452                     mKeySize,
453                     mSpec,
454                     mSubjectDN,
455                     mSerialNumber,
456                     mStartDate,
457                     mEndDate,
458                     mFlags);
459         }
460     }
461 }
462