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