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 <a href="{@docRoot}
255      * training/articles/keystore.html">Android KeyStore facility</a>.
256      * <p>
257      * The required fields must be filled in with the builder.
258      * <p>
259      * Example:
260      *
261      * <pre class="prettyprint">
262      * Calendar start = new Calendar();
263      * Calendar end = new Calendar();
264      * end.add(1, Calendar.YEAR);
265      *
266      * KeyPairGeneratorSpec spec =
267      *         new KeyPairGeneratorSpec.Builder(mContext).setAlias(&quot;myKey&quot;)
268      *                 .setSubject(new X500Principal(&quot;CN=myKey&quot;)).setSerial(BigInteger.valueOf(1337))
269      *                 .setStartDate(start.getTime()).setEndDate(end.getTime()).build();
270      * </pre>
271      *
272      *  @deprecated Use {@link KeyGenParameterSpec.Builder} instead.
273      */
274     @Deprecated
275     public final static class Builder {
276         private final Context mContext;
277 
278         private String mKeystoreAlias;
279 
280         private String mKeyType;
281 
282         private int mKeySize = -1;
283 
284         private AlgorithmParameterSpec mSpec;
285 
286         private X500Principal mSubjectDN;
287 
288         private BigInteger mSerialNumber;
289 
290         private Date mStartDate;
291 
292         private Date mEndDate;
293 
294         private int mFlags;
295 
296         /**
297          * Creates a new instance of the {@code Builder} with the given
298          * {@code context}. The {@code context} passed in may be used to pop up
299          * some UI to ask the user to unlock or initialize the Android KeyStore
300          * facility.
301          */
Builder(@onNull Context context)302         public Builder(@NonNull Context context) {
303             if (context == null) {
304                 throw new NullPointerException("context == null");
305             }
306             mContext = context;
307         }
308 
309         /**
310          * Sets the alias to be used to retrieve the key later from a
311          * {@link java.security.KeyStore} instance using the
312          * {@code AndroidKeyStore} provider.
313          */
314         @NonNull
setAlias(@onNull String alias)315         public Builder setAlias(@NonNull String alias) {
316             if (alias == null) {
317                 throw new NullPointerException("alias == null");
318             }
319             mKeystoreAlias = alias;
320             return this;
321         }
322 
323         /**
324          * Sets the type of key pair (e.g., {@code EC}, {@code RSA}) of the key pair to be
325          * generated. See {@link KeyProperties}.{@code KEY_ALGORITHM} constants.
326          *
327          */
328         @NonNull
setKeyType(@onNull @eyProperties.KeyAlgorithmEnum String keyType)329         public Builder setKeyType(@NonNull @KeyProperties.KeyAlgorithmEnum String keyType)
330                 throws NoSuchAlgorithmException {
331             if (keyType == null) {
332                 throw new NullPointerException("keyType == null");
333             } else {
334                 try {
335                     KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(keyType);
336                 } catch (IllegalArgumentException e) {
337                     throw new NoSuchAlgorithmException("Unsupported key type: " + keyType);
338                 }
339             }
340             mKeyType = keyType;
341             return this;
342         }
343 
344         /**
345          * Sets the key size for the keypair to be created. For instance, for a
346          * key type of RSA this will set the modulus size and for a key type of
347          * EC it will select a curve with a matching field size.
348          */
349         @NonNull
setKeySize(int keySize)350         public Builder setKeySize(int keySize) {
351             if (keySize < 0) {
352                 throw new IllegalArgumentException("keySize < 0");
353             }
354             mKeySize = keySize;
355             return this;
356         }
357 
358         /**
359          * Sets the algorithm-specific key generation parameters. For example, for RSA keys
360          * this may be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}.
361          */
setAlgorithmParameterSpec(@onNull AlgorithmParameterSpec spec)362         public Builder setAlgorithmParameterSpec(@NonNull AlgorithmParameterSpec spec) {
363             if (spec == null) {
364                 throw new NullPointerException("spec == null");
365             }
366             mSpec = spec;
367             return this;
368         }
369 
370         /**
371          * Sets the subject used for the self-signed certificate of the
372          * generated key pair.
373          */
374         @NonNull
setSubject(@onNull X500Principal subject)375         public Builder setSubject(@NonNull X500Principal subject) {
376             if (subject == null) {
377                 throw new NullPointerException("subject == null");
378             }
379             mSubjectDN = subject;
380             return this;
381         }
382 
383         /**
384          * Sets the serial number used for the self-signed certificate of the
385          * generated key pair.
386          */
387         @NonNull
setSerialNumber(@onNull BigInteger serialNumber)388         public Builder setSerialNumber(@NonNull BigInteger serialNumber) {
389             if (serialNumber == null) {
390                 throw new NullPointerException("serialNumber == null");
391             }
392             mSerialNumber = serialNumber;
393             return this;
394         }
395 
396         /**
397          * Sets the start of the validity period for the self-signed certificate
398          * of the generated key pair.
399          */
400         @NonNull
setStartDate(@onNull Date startDate)401         public Builder setStartDate(@NonNull Date startDate) {
402             if (startDate == null) {
403                 throw new NullPointerException("startDate == null");
404             }
405             mStartDate = startDate;
406             return this;
407         }
408 
409         /**
410          * Sets the end of the validity period for the self-signed certificate
411          * of the generated key pair.
412          */
413         @NonNull
setEndDate(@onNull Date endDate)414         public Builder setEndDate(@NonNull Date endDate) {
415             if (endDate == null) {
416                 throw new NullPointerException("endDate == null");
417             }
418             mEndDate = endDate;
419             return this;
420         }
421 
422         /**
423          * Indicates that this key pair must be encrypted at rest. This will protect the key pair
424          * with the secure lock screen credential (e.g., password, PIN, or pattern).
425          *
426          * <p>Note that this feature requires that the secure lock screen (e.g., password, PIN,
427          * pattern) is set up, otherwise key pair generation will fail. Moreover, this key pair will
428          * be deleted when the secure lock screen is disabled or reset (e.g., by the user or a
429          * Device Administrator). Finally, this key pair cannot be used until the user unlocks the
430          * secure lock screen after boot.
431          *
432          * @see KeyguardManager#isDeviceSecure()
433          */
434         @NonNull
setEncryptionRequired()435         public Builder setEncryptionRequired() {
436             mFlags |= KeyStore.FLAG_ENCRYPTED;
437             return this;
438         }
439 
440         /**
441          * Builds the instance of the {@code KeyPairGeneratorSpec}.
442          *
443          * @throws IllegalArgumentException if a required field is missing
444          * @return built instance of {@code KeyPairGeneratorSpec}
445          */
446         @NonNull
build()447         public KeyPairGeneratorSpec build() {
448             return new KeyPairGeneratorSpec(mContext,
449                     mKeystoreAlias,
450                     mKeyType,
451                     mKeySize,
452                     mSpec,
453                     mSubjectDN,
454                     mSerialNumber,
455                     mStartDate,
456                     mEndDate,
457                     mFlags);
458         }
459     }
460 }
461