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("myKey") 269 * .setSubject(new X500Principal("CN=myKey")).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