blob: a43952a8104871716cdea793c12f5ef118d9faea [file] [log] [blame]
Robert Berry81ee34b2018-01-23 11:59:59 +00001/*
2 * Copyright (C) 2017 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.keystore.recovery;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
Dmitry Dementyevf8ae5de2018-01-08 18:08:23 -080021import android.annotation.SystemApi;
Robert Berry81ee34b2018-01-23 11:59:59 +000022import android.os.Parcel;
23import android.os.Parcelable;
24
25import com.android.internal.util.Preconditions;
26
27import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
29import java.util.Arrays;
30
31/**
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080032 * A {@link KeyChainSnapshot} is protected with a key derived from the user's lock screen. This
Robert Berry81ee34b2018-01-23 11:59:59 +000033 * class wraps all the data necessary to derive the same key on a recovering device:
34 *
35 * <ul>
36 * <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
37 * the recovering device can display the pattern UI to the user when asking them to enter
38 * the lock screen from their previous device.
39 * <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
40 * </ul>
41 *
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080042 * <p>As such, this data is sent along with the {@link KeyChainSnapshot} when syncing the current
Robert Berry81ee34b2018-01-23 11:59:59 +000043 * version of the keychain.
44 *
45 * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
46 * user's lock screen. In the future, the keychain will support multiple layers of protection
47 * (e.g. an additional keychain password, along with the lock screen).
48 *
49 * @hide
50 */
Dmitry Dementyevf8ae5de2018-01-08 18:08:23 -080051@SystemApi
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080052public final class KeyChainProtectionParams implements Parcelable {
Robert Berry81ee34b2018-01-23 11:59:59 +000053 /** @hide */
54 @Retention(RetentionPolicy.SOURCE)
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080055 @IntDef(prefix = {"TYPE_"}, value = {TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
Robert Berry81ee34b2018-01-23 11:59:59 +000056 public @interface UserSecretType {
57 }
58
59 /**
60 * Lockscreen secret is required to recover KeyStore.
61 */
62 public static final int TYPE_LOCKSCREEN = 100;
63
64 /**
65 * Custom passphrase, unrelated to lock screen, is required to recover KeyStore.
66 */
67 public static final int TYPE_CUSTOM_PASSWORD = 101;
68
69 /** @hide */
70 @Retention(RetentionPolicy.SOURCE)
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080071 @IntDef(prefix = {"UI_FORMAT_"}, value = {UI_FORMAT_PIN, UI_FORMAT_PASSWORD, UI_FORMAT_PATTERN})
Robert Berry81ee34b2018-01-23 11:59:59 +000072 public @interface LockScreenUiFormat {
73 }
74
75 /**
76 * Pin with digits only.
77 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080078 public static final int UI_FORMAT_PIN = 1;
Robert Berry81ee34b2018-01-23 11:59:59 +000079
80 /**
81 * Password. String with latin-1 characters only.
82 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080083 public static final int UI_FORMAT_PASSWORD = 2;
Robert Berry81ee34b2018-01-23 11:59:59 +000084
85 /**
86 * Pattern with 3 by 3 grid.
87 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080088 public static final int UI_FORMAT_PATTERN = 3;
Robert Berry81ee34b2018-01-23 11:59:59 +000089
90 @UserSecretType
91 private Integer mUserSecretType;
92
93 @LockScreenUiFormat
94 private Integer mLockScreenUiFormat;
95
96 /**
97 * Parameters of the key derivation function, including algorithm, difficulty, salt.
98 */
99 private KeyDerivationParams mKeyDerivationParams;
100 private byte[] mSecret; // Derived from user secret. The field must have limited visibility.
101
102 /**
103 * @param secret Constructor creates a reference to the secret. Caller must use
104 * @link {#clearSecret} to overwrite its value in memory.
105 * @hide
106 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800107 public KeyChainProtectionParams(@UserSecretType int userSecretType,
Robert Berry81ee34b2018-01-23 11:59:59 +0000108 @LockScreenUiFormat int lockScreenUiFormat,
109 @NonNull KeyDerivationParams keyDerivationParams,
110 @NonNull byte[] secret) {
111 mUserSecretType = userSecretType;
112 mLockScreenUiFormat = lockScreenUiFormat;
113 mKeyDerivationParams = Preconditions.checkNotNull(keyDerivationParams);
114 mSecret = Preconditions.checkNotNull(secret);
115 }
116
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800117 private KeyChainProtectionParams() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000118
119 }
120
121 /**
122 * @see TYPE_LOCKSCREEN
123 * @see TYPE_CUSTOM_PASSWORD
124 */
125 public @UserSecretType int getUserSecretType() {
126 return mUserSecretType;
127 }
128
129 /**
130 * Specifies UX shown to user during recovery.
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800131 * Default value is {@code UI_FORMAT_LOCKSCREEN}
Robert Berry81ee34b2018-01-23 11:59:59 +0000132 *
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800133 * @see UI_FORMAT_PIN
134 * @see UI_FORMAT_PASSWORD
135 * @see UI_FORMAT_PATTERN
Robert Berry81ee34b2018-01-23 11:59:59 +0000136 */
137 public @LockScreenUiFormat int getLockScreenUiFormat() {
138 return mLockScreenUiFormat;
139 }
140
141 /**
142 * Specifies function used to derive symmetric key from user input
143 * Format is defined in separate util class.
144 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800145 public @NonNull KeyDerivationParams getKeyDerivationParams() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000146 return mKeyDerivationParams;
147 }
148
149 /**
150 * Secret derived from user input.
151 * Default value is empty array
152 *
153 * @return secret or empty array
154 */
155 public @NonNull byte[] getSecret() {
156 return mSecret;
157 }
158
159 /**
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800160 * Builder for creating {@link KeyChainProtectionParams}.
Robert Berry81ee34b2018-01-23 11:59:59 +0000161 */
162 public static class Builder {
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800163 private KeyChainProtectionParams mInstance = new KeyChainProtectionParams();
Robert Berry81ee34b2018-01-23 11:59:59 +0000164
165 /**
166 * Sets user secret type.
167 *
168 * @see TYPE_LOCKSCREEN
169 * @see TYPE_CUSTOM_PASSWORD
170 * @param userSecretType The secret type
171 * @return This builder.
172 */
173 public Builder setUserSecretType(@UserSecretType int userSecretType) {
174 mInstance.mUserSecretType = userSecretType;
175 return this;
176 }
177
178 /**
179 * Sets UI format.
180 *
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800181 * @see UI_FORMAT_PIN
182 * @see UI_FORMAT_PASSWORD
183 * @see UI_FORMAT_PATTERN
Robert Berry81ee34b2018-01-23 11:59:59 +0000184 * @param lockScreenUiFormat The UI format
185 * @return This builder.
186 */
187 public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
188 mInstance.mLockScreenUiFormat = lockScreenUiFormat;
189 return this;
190 }
191
192 /**
193 * Sets parameters of the key derivation function.
194 *
195 * @param keyDerivationParams Key derivation Params
196 * @return This builder.
197 */
198 public Builder setKeyDerivationParams(@NonNull KeyDerivationParams
199 keyDerivationParams) {
200 mInstance.mKeyDerivationParams = keyDerivationParams;
201 return this;
202 }
203
204 /**
205 * Secret derived from user input, or empty array.
206 *
207 * @param secret The secret.
208 * @return This builder.
209 */
210 public Builder setSecret(@NonNull byte[] secret) {
211 mInstance.mSecret = secret;
212 return this;
213 }
214
215
216 /**
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800217 * Creates a new {@link KeyChainProtectionParams} instance.
Robert Berry81ee34b2018-01-23 11:59:59 +0000218 * The instance will include default values, if {@link setSecret}
219 * or {@link setUserSecretType} were not called.
220 *
221 * @return new instance
222 * @throws NullPointerException if some required fields were not set.
223 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800224 @NonNull public KeyChainProtectionParams build() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000225 if (mInstance.mUserSecretType == null) {
226 mInstance.mUserSecretType = TYPE_LOCKSCREEN;
227 }
228 Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
229 Preconditions.checkNotNull(mInstance.mKeyDerivationParams);
230 if (mInstance.mSecret == null) {
231 mInstance.mSecret = new byte[]{};
232 }
233 return mInstance;
234 }
235 }
236
237 /**
238 * Removes secret from memory than object is no longer used.
239 * Since finalizer call is not reliable, please use @link {#clearSecret} directly.
240 */
241 @Override
242 protected void finalize() throws Throwable {
243 clearSecret();
244 super.finalize();
245 }
246
247 /**
248 * Fills mSecret with zeroes.
249 */
250 public void clearSecret() {
251 Arrays.fill(mSecret, (byte) 0);
252 }
253
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800254 public static final Parcelable.Creator<KeyChainProtectionParams> CREATOR =
255 new Parcelable.Creator<KeyChainProtectionParams>() {
256 public KeyChainProtectionParams createFromParcel(Parcel in) {
257 return new KeyChainProtectionParams(in);
Robert Berry81ee34b2018-01-23 11:59:59 +0000258 }
259
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800260 public KeyChainProtectionParams[] newArray(int length) {
261 return new KeyChainProtectionParams[length];
Robert Berry81ee34b2018-01-23 11:59:59 +0000262 }
263 };
264
Robert Berry81ee34b2018-01-23 11:59:59 +0000265 @Override
266 public void writeToParcel(Parcel out, int flags) {
267 out.writeInt(mUserSecretType);
268 out.writeInt(mLockScreenUiFormat);
269 out.writeTypedObject(mKeyDerivationParams, flags);
270 out.writeByteArray(mSecret);
271 }
272
273 /**
274 * @hide
275 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800276 protected KeyChainProtectionParams(Parcel in) {
Robert Berry81ee34b2018-01-23 11:59:59 +0000277 mUserSecretType = in.readInt();
278 mLockScreenUiFormat = in.readInt();
279 mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
280 mSecret = in.createByteArray();
281 }
282
283 @Override
284 public int describeContents() {
285 return 0;
286 }
287}