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