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.content.Context; 20 import android.text.TextUtils; 21 22 import java.math.BigInteger; 23 import java.security.PrivateKey; 24 import java.security.cert.Certificate; 25 import java.security.spec.AlgorithmParameterSpec; 26 import java.util.Date; 27 28 import javax.security.auth.x500.X500Principal; 29 30 /** 31 * This provides the required parameters needed for initializing the 32 * {@code KeyPairGenerator} that works with 33 * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore 34 * facility</a>. The Android KeyStore facility is accessed through a 35 * {@link java.security.KeyPairGenerator} API using the {@code AndroidKeyStore} 36 * provider. The {@code context} passed in may be used to pop up some UI to ask 37 * the user to unlock or initialize the Android KeyStore facility. 38 * <p> 39 * After generation, the {@code keyStoreAlias} is used with the 40 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)} 41 * interface to retrieve the {@link PrivateKey} and its associated 42 * {@link Certificate} chain. 43 * <p> 44 * The KeyPair generator will create a self-signed certificate with the subject 45 * as its X.509v3 Subject Distinguished Name and as its X.509v3 Issuer 46 * Distinguished Name along with the other parameters specified with the 47 * {@link Builder}. 48 * <p> 49 * The self-signed X.509 certificate may be replaced at a later time by a 50 * certificate signed by a real Certificate Authority. 51 */ 52 public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { 53 private final String mKeystoreAlias; 54 55 private final Context mContext; 56 57 private final X500Principal mSubjectDN; 58 59 private final BigInteger mSerialNumber; 60 61 private final Date mStartDate; 62 63 private final Date mEndDate; 64 65 private final int mFlags; 66 67 /** 68 * Parameter specification for the "{@code AndroidKeyPairGenerator}" 69 * instance of the {@link java.security.KeyPairGenerator} API. The 70 * {@code context} passed in may be used to pop up some UI to ask the user 71 * to unlock or initialize the Android keystore facility. 72 * <p> 73 * After generation, the {@code keyStoreAlias} is used with the 74 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)} 75 * interface to retrieve the {@link PrivateKey} and its associated 76 * {@link Certificate} chain. 77 * <p> 78 * The KeyPair generator will create a self-signed certificate with the 79 * properties of {@code subjectDN} as its X.509v3 Subject Distinguished Name 80 * and as its X.509v3 Issuer Distinguished Name, using the specified 81 * {@code serialNumber}, and the validity date starting at {@code startDate} 82 * and ending at {@code endDate}. 83 * 84 * @param context Android context for the activity 85 * @param keyStoreAlias name to use for the generated key in the Android 86 * keystore 87 * @param subjectDN X.509 v3 Subject Distinguished Name 88 * @param serialNumber X509 v3 certificate serial number 89 * @param startDate the start of the self-signed certificate validity period 90 * @param endDate the end date of the self-signed certificate validity 91 * period 92 * @throws IllegalArgumentException when any argument is {@code null} or 93 * {@code endDate} is before {@code startDate}. 94 * @hide should be built with KeyPairGeneratorSpecBuilder 95 */ 96 public KeyPairGeneratorSpec(Context context, String keyStoreAlias, 97 X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, 98 int flags) { 99 if (context == null) { 100 throw new IllegalArgumentException("context == null"); 101 } else if (TextUtils.isEmpty(keyStoreAlias)) { 102 throw new IllegalArgumentException("keyStoreAlias must not be empty"); 103 } else if (subjectDN == null) { 104 throw new IllegalArgumentException("subjectDN == null"); 105 } else if (serialNumber == null) { 106 throw new IllegalArgumentException("serialNumber == null"); 107 } else if (startDate == null) { 108 throw new IllegalArgumentException("startDate == null"); 109 } else if (endDate == null) { 110 throw new IllegalArgumentException("endDate == null"); 111 } else if (endDate.before(startDate)) { 112 throw new IllegalArgumentException("endDate < startDate"); 113 } 114 115 mContext = context; 116 mKeystoreAlias = keyStoreAlias; 117 mSubjectDN = subjectDN; 118 mSerialNumber = serialNumber; 119 mStartDate = startDate; 120 mEndDate = endDate; 121 mFlags = flags; 122 } 123 124 /** 125 * Returns the alias that will be used in the {@code java.security.KeyStore} 126 * in conjunction with the {@code AndroidKeyStore}. 127 */ 128 public String getKeystoreAlias() { 129 return mKeystoreAlias; 130 } 131 132 /** 133 * Gets the Android context used for operations with this instance. 134 */ 135 public Context getContext() { 136 return mContext; 137 } 138 139 /** 140 * Gets the subject distinguished name to be used on the X.509 certificate 141 * that will be put in the {@link java.security.KeyStore}. 142 */ 143 public X500Principal getSubjectDN() { 144 return mSubjectDN; 145 } 146 147 /** 148 * Gets the serial number to be used on the X.509 certificate that will be 149 * put in the {@link java.security.KeyStore}. 150 */ 151 public BigInteger getSerialNumber() { 152 return mSerialNumber; 153 } 154 155 /** 156 * Gets the start date to be used on the X.509 certificate that will be put 157 * in the {@link java.security.KeyStore}. 158 */ 159 public Date getStartDate() { 160 return mStartDate; 161 } 162 163 /** 164 * Gets the end date to be used on the X.509 certificate that will be put in 165 * the {@link java.security.KeyStore}. 166 */ 167 public Date getEndDate() { 168 return mEndDate; 169 } 170 171 /** 172 * @hide 173 */ 174 int getFlags() { 175 return mFlags; 176 } 177 178 /** 179 * Returns {@code true} if this parameter will require generated keys to be 180 * encrypted in the {@link java.security.KeyStore}. 181 */ 182 public boolean isEncryptionRequired() { 183 return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0; 184 } 185 186 /** 187 * Builder class for {@link KeyPairGeneratorSpec} objects. 188 * <p> 189 * This will build a parameter spec for use with the <a href="{@docRoot} 190 * guide/topics/security/keystore.html">Android KeyStore facility</a>. 191 * <p> 192 * The required fields must be filled in with the builder. 193 * <p> 194 * Example: 195 * 196 * <pre class="prettyprint"> 197 * Calendar start = new Calendar(); 198 * Calendar end = new Calendar(); 199 * end.add(1, Calendar.YEAR); 200 * 201 * KeyPairGeneratorSpec spec = 202 * new KeyPairGeneratorSpec.Builder(mContext).setAlias("myKey") 203 * .setSubject(new X500Principal("CN=myKey")).setSerial(BigInteger.valueOf(1337)) 204 * .setStartDate(start.getTime()).setEndDate(end.getTime()).build(); 205 * </pre> 206 */ 207 public final static class Builder { 208 private final Context mContext; 209 210 private String mKeystoreAlias; 211 212 private X500Principal mSubjectDN; 213 214 private BigInteger mSerialNumber; 215 216 private Date mStartDate; 217 218 private Date mEndDate; 219 220 private int mFlags; 221 222 /** 223 * Creates a new instance of the {@code Builder} with the given 224 * {@code context}. The {@code context} passed in may be used to pop up 225 * some UI to ask the user to unlock or initialize the Android KeyStore 226 * facility. 227 */ 228 public Builder(Context context) { 229 if (context == null) { 230 throw new NullPointerException("context == null"); 231 } 232 mContext = context; 233 } 234 235 /** 236 * Sets the alias to be used to retrieve the key later from a 237 * {@link java.security.KeyStore} instance using the 238 * {@code AndroidKeyStore} provider. 239 */ 240 public Builder setAlias(String alias) { 241 if (alias == null) { 242 throw new NullPointerException("alias == null"); 243 } 244 mKeystoreAlias = alias; 245 return this; 246 } 247 248 /** 249 * Sets the subject used for the self-signed certificate of the 250 * generated key pair. 251 */ 252 public Builder setSubject(X500Principal subject) { 253 if (subject == null) { 254 throw new NullPointerException("subject == null"); 255 } 256 mSubjectDN = subject; 257 return this; 258 } 259 260 /** 261 * Sets the serial number used for the self-signed certificate of the 262 * generated key pair. 263 */ 264 public Builder setSerialNumber(BigInteger serialNumber) { 265 if (serialNumber == null) { 266 throw new NullPointerException("serialNumber == null"); 267 } 268 mSerialNumber = serialNumber; 269 return this; 270 } 271 272 /** 273 * Sets the start of the validity period for the self-signed certificate 274 * of the generated key pair. 275 */ 276 public Builder setStartDate(Date startDate) { 277 if (startDate == null) { 278 throw new NullPointerException("startDate == null"); 279 } 280 mStartDate = startDate; 281 return this; 282 } 283 284 /** 285 * Sets the end of the validity period for the self-signed certificate 286 * of the generated key pair. 287 */ 288 public Builder setEndDate(Date endDate) { 289 if (endDate == null) { 290 throw new NullPointerException("endDate == null"); 291 } 292 mEndDate = endDate; 293 return this; 294 } 295 296 /** 297 * Indicates that this key must be encrypted at rest on storage. Note 298 * that enabling this will require that the user enable a strong lock 299 * screen (e.g., PIN, password) before creating or using the generated 300 * key is successful. 301 */ 302 public Builder setEncryptionRequired() { 303 mFlags |= KeyStore.FLAG_ENCRYPTED; 304 return this; 305 } 306 307 /** 308 * Builds the instance of the {@code KeyPairGeneratorSpec}. 309 * 310 * @throws IllegalArgumentException if a required field is missing 311 * @return built instance of {@code KeyPairGeneratorSpec} 312 */ 313 public KeyPairGeneratorSpec build() { 314 return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN, 315 mSerialNumber, mStartDate, mEndDate, mFlags); 316 } 317 } 318 } 319