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