blob: 4af1af5f90cf292e4e3ed71a5314aa76e5ef1941 [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 Berry52c15f12018-03-29 10:21:50 +010053
54 // IMPORTANT! PLEASE READ!
55 // -----------------------
56 // If you edit this file (e.g., to add new fields), please MAKE SURE to also do the following:
57 // - Update the #writeToParcel(Parcel) method below
58 // - Update the #(Parcel) constructor below
59 // - Update android.security.keystore.recovery.KeyChainSnapshotTest to make sure nobody
60 // accidentally breaks your fields in the Parcel in the future.
61 // - Update com.android.server.locksettings.recoverablekeystore.serialization
62 // .KeyChainSnapshotSerializer to correctly serialize your new field
63 // - Update com.android.server.locksettings.recoverablekeystore.serialization
64 // .KeyChainSnapshotSerializer to correctly deserialize your new field
65 // - Update com.android.server.locksettings.recoverablekeystore.serialization
66 // .KeychainSnapshotSerializerTest to make sure nobody breaks serialization of your field
67 // in the future.
68
Robert Berry81ee34b2018-01-23 11:59:59 +000069 /** @hide */
70 @Retention(RetentionPolicy.SOURCE)
Aseem Kumar933dfc12018-03-22 22:09:34 -070071 @IntDef(prefix = {"TYPE_"}, value = {TYPE_LOCKSCREEN})
Robert Berry81ee34b2018-01-23 11:59:59 +000072 public @interface UserSecretType {
73 }
74
75 /**
76 * Lockscreen secret is required to recover KeyStore.
77 */
78 public static final int TYPE_LOCKSCREEN = 100;
79
Robert Berry81ee34b2018-01-23 11:59:59 +000080 /** @hide */
81 @Retention(RetentionPolicy.SOURCE)
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080082 @IntDef(prefix = {"UI_FORMAT_"}, value = {UI_FORMAT_PIN, UI_FORMAT_PASSWORD, UI_FORMAT_PATTERN})
Robert Berry81ee34b2018-01-23 11:59:59 +000083 public @interface LockScreenUiFormat {
84 }
85
86 /**
87 * Pin with digits only.
88 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080089 public static final int UI_FORMAT_PIN = 1;
Robert Berry81ee34b2018-01-23 11:59:59 +000090
91 /**
92 * Password. String with latin-1 characters only.
93 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080094 public static final int UI_FORMAT_PASSWORD = 2;
Robert Berry81ee34b2018-01-23 11:59:59 +000095
96 /**
97 * Pattern with 3 by 3 grid.
98 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080099 public static final int UI_FORMAT_PATTERN = 3;
Robert Berry81ee34b2018-01-23 11:59:59 +0000100
101 @UserSecretType
102 private Integer mUserSecretType;
103
104 @LockScreenUiFormat
105 private Integer mLockScreenUiFormat;
106
107 /**
108 * Parameters of the key derivation function, including algorithm, difficulty, salt.
109 */
110 private KeyDerivationParams mKeyDerivationParams;
111 private byte[] mSecret; // Derived from user secret. The field must have limited visibility.
112
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800113 private KeyChainProtectionParams() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000114
115 }
116
117 /**
118 * @see TYPE_LOCKSCREEN
Robert Berry81ee34b2018-01-23 11:59:59 +0000119 */
120 public @UserSecretType int getUserSecretType() {
121 return mUserSecretType;
122 }
123
124 /**
125 * Specifies UX shown to user during recovery.
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800126 * Default value is {@code UI_FORMAT_LOCKSCREEN}
Robert Berry81ee34b2018-01-23 11:59:59 +0000127 *
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800128 * @see UI_FORMAT_PIN
129 * @see UI_FORMAT_PASSWORD
130 * @see UI_FORMAT_PATTERN
Robert Berry81ee34b2018-01-23 11:59:59 +0000131 */
132 public @LockScreenUiFormat int getLockScreenUiFormat() {
133 return mLockScreenUiFormat;
134 }
135
136 /**
137 * Specifies function used to derive symmetric key from user input
138 * Format is defined in separate util class.
139 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800140 public @NonNull KeyDerivationParams getKeyDerivationParams() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000141 return mKeyDerivationParams;
142 }
143
144 /**
145 * Secret derived from user input.
146 * Default value is empty array
147 *
148 * @return secret or empty array
149 */
150 public @NonNull byte[] getSecret() {
151 return mSecret;
152 }
153
154 /**
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800155 * Builder for creating {@link KeyChainProtectionParams}.
Robert Berry81ee34b2018-01-23 11:59:59 +0000156 */
157 public static class Builder {
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800158 private KeyChainProtectionParams mInstance = new KeyChainProtectionParams();
Robert Berry81ee34b2018-01-23 11:59:59 +0000159
160 /**
161 * Sets user secret type.
Dmitry Dementyev16d9db52018-03-26 11:31:46 -0700162 * Default value is {@link TYPE_LOCKSCREEN}.
Robert Berry81ee34b2018-01-23 11:59:59 +0000163 *
164 * @see TYPE_LOCKSCREEN
Robert Berry81ee34b2018-01-23 11:59:59 +0000165 * @param userSecretType The secret type
166 * @return This builder.
167 */
168 public Builder setUserSecretType(@UserSecretType int userSecretType) {
169 mInstance.mUserSecretType = userSecretType;
170 return this;
171 }
172
173 /**
174 * Sets UI format.
175 *
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800176 * @see UI_FORMAT_PIN
177 * @see UI_FORMAT_PASSWORD
178 * @see UI_FORMAT_PATTERN
Robert Berry81ee34b2018-01-23 11:59:59 +0000179 * @param lockScreenUiFormat The UI format
180 * @return This builder.
181 */
182 public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
183 mInstance.mLockScreenUiFormat = lockScreenUiFormat;
184 return this;
185 }
186
187 /**
188 * Sets parameters of the key derivation function.
189 *
Dmitry Dementyev16d9db52018-03-26 11:31:46 -0700190 * @param keyDerivationParams Key derivation parameters
Robert Berry81ee34b2018-01-23 11:59:59 +0000191 * @return This builder.
192 */
193 public Builder setKeyDerivationParams(@NonNull KeyDerivationParams
194 keyDerivationParams) {
195 mInstance.mKeyDerivationParams = keyDerivationParams;
196 return this;
197 }
198
199 /**
200 * Secret derived from user input, or empty array.
201 *
202 * @param secret The secret.
203 * @return This builder.
204 */
205 public Builder setSecret(@NonNull byte[] secret) {
206 mInstance.mSecret = secret;
207 return this;
208 }
209
210
211 /**
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800212 * Creates a new {@link KeyChainProtectionParams} instance.
Aseem Kumarc1742e52018-03-12 14:34:58 -0700213 * The instance will include default values, if {@link #setSecret}
214 * or {@link #setUserSecretType} were not called.
Robert Berry81ee34b2018-01-23 11:59:59 +0000215 *
216 * @return new instance
217 * @throws NullPointerException if some required fields were not set.
218 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800219 @NonNull public KeyChainProtectionParams build() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000220 if (mInstance.mUserSecretType == null) {
221 mInstance.mUserSecretType = TYPE_LOCKSCREEN;
222 }
223 Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
224 Preconditions.checkNotNull(mInstance.mKeyDerivationParams);
225 if (mInstance.mSecret == null) {
226 mInstance.mSecret = new byte[]{};
227 }
228 return mInstance;
229 }
230 }
231
232 /**
Dmitry Dementyev19da3402018-01-30 13:16:47 -0800233 * Fills secret with zeroes.
Robert Berry81ee34b2018-01-23 11:59:59 +0000234 */
235 public void clearSecret() {
236 Arrays.fill(mSecret, (byte) 0);
237 }
238
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800239 public static final Parcelable.Creator<KeyChainProtectionParams> CREATOR =
240 new Parcelable.Creator<KeyChainProtectionParams>() {
241 public KeyChainProtectionParams createFromParcel(Parcel in) {
242 return new KeyChainProtectionParams(in);
Robert Berry81ee34b2018-01-23 11:59:59 +0000243 }
244
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800245 public KeyChainProtectionParams[] newArray(int length) {
246 return new KeyChainProtectionParams[length];
Robert Berry81ee34b2018-01-23 11:59:59 +0000247 }
248 };
249
Robert Berry81ee34b2018-01-23 11:59:59 +0000250 @Override
251 public void writeToParcel(Parcel out, int flags) {
252 out.writeInt(mUserSecretType);
253 out.writeInt(mLockScreenUiFormat);
254 out.writeTypedObject(mKeyDerivationParams, flags);
255 out.writeByteArray(mSecret);
256 }
257
258 /**
259 * @hide
260 */
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800261 protected KeyChainProtectionParams(Parcel in) {
Robert Berry81ee34b2018-01-23 11:59:59 +0000262 mUserSecretType = in.readInt();
263 mLockScreenUiFormat = in.readInt();
264 mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
265 mSecret = in.createByteArray();
266 }
267
268 @Override
269 public int describeContents() {
270 return 0;
271 }
272}