blob: d036d144aaa1c5b33d07add4d6e8029c84294cd9 [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;
29
30/**
31 * Collection of parameters which define a key derivation function.
Aseem Kumarc1742e52018-03-12 14:34:58 -070032 * Currently only supports salted SHA-256.
Robert Berry81ee34b2018-01-23 11:59:59 +000033 *
34 * @hide
35 */
Dmitry Dementyevf8ae5de2018-01-08 18:08:23 -080036@SystemApi
Robert Berry81ee34b2018-01-23 11:59:59 +000037public final class KeyDerivationParams implements Parcelable {
Robert Berry52c15f12018-03-29 10:21:50 +010038
39 // IMPORTANT! PLEASE READ!
40 // -----------------------
41 // If you edit this file (e.g., to add new fields), please MAKE SURE to also do the following:
42 // - Update the #writeToParcel(Parcel) method below
43 // - Update the #(Parcel) constructor below
44 // - Update android.security.keystore.recovery.KeyChainSnapshotTest to make sure nobody
45 // accidentally breaks your fields in the Parcel in the future.
46 // - Update com.android.server.locksettings.recoverablekeystore.serialization
47 // .KeyChainSnapshotSerializer to correctly serialize your new field
48 // - Update com.android.server.locksettings.recoverablekeystore.serialization
49 // .KeyChainSnapshotSerializer to correctly deserialize your new field
50 // - Update com.android.server.locksettings.recoverablekeystore.serialization
51 // .KeychainSnapshotSerializerTest to make sure nobody breaks serialization of your field
52 // in the future.
53
Robert Berry81ee34b2018-01-23 11:59:59 +000054 private final int mAlgorithm;
Bo Zhue066a592018-03-19 22:32:27 -070055 private final byte[] mSalt;
Bo Zhu40d8a45b2018-03-21 20:07:43 -070056 private final int mMemoryDifficulty;
Robert Berry81ee34b2018-01-23 11:59:59 +000057
58 /** @hide */
59 @Retention(RetentionPolicy.SOURCE)
Bo Zhue066a592018-03-19 22:32:27 -070060 @IntDef(prefix = {"ALGORITHM_"}, value = {ALGORITHM_SHA256, ALGORITHM_SCRYPT})
Robert Berry81ee34b2018-01-23 11:59:59 +000061 public @interface KeyDerivationAlgorithm {
62 }
63
64 /**
Bo Zhue066a592018-03-19 22:32:27 -070065 * Salted SHA256.
Robert Berry81ee34b2018-01-23 11:59:59 +000066 */
67 public static final int ALGORITHM_SHA256 = 1;
68
69 /**
Bo Zhue066a592018-03-19 22:32:27 -070070 * SCRYPT.
Robert Berry81ee34b2018-01-23 11:59:59 +000071 */
Bo Zhue066a592018-03-19 22:32:27 -070072 public static final int ALGORITHM_SCRYPT = 2;
Robert Berry81ee34b2018-01-23 11:59:59 +000073
74 /**
Bo Zhu40d8a45b2018-03-21 20:07:43 -070075 * Creates instance of the class to to derive keys using salted SHA256 hash.
76 *
77 * <p>The salted SHA256 hash is computed over the concatenation of four byte strings, salt_len +
Bo Zhuba94b9a2018-03-29 16:42:29 -070078 * salt + key_material_len + key_material, where salt_len and key_material_len are 4-byte, and
Bo Zhu40d8a45b2018-03-21 20:07:43 -070079 * denote the number of bytes for salt and key_material, respectively.
Robert Berry81ee34b2018-01-23 11:59:59 +000080 */
Dmitry Dementyevfd4ae0b2018-03-23 11:06:24 -070081 public static @NonNull KeyDerivationParams createSha256Params(@NonNull byte[] salt) {
Robert Berry81ee34b2018-01-23 11:59:59 +000082 return new KeyDerivationParams(ALGORITHM_SHA256, salt);
83 }
84
Dmitry Dementyevf8ae5de2018-01-08 18:08:23 -080085 /**
Bo Zhu40d8a45b2018-03-21 20:07:43 -070086 * Creates instance of the class to to derive keys using the password hashing algorithm SCRYPT.
Bo Zhue066a592018-03-19 22:32:27 -070087 *
Bo Zhu40d8a45b2018-03-21 20:07:43 -070088 * <p>We expose only one tuning parameter of SCRYPT, which is the memory cost parameter (i.e. N
89 * in <a href="https://www.tarsnap.com/scrypt/scrypt.pdf">the SCRYPT paper</a>). Regular/default
90 * values are used for the other parameters, to keep the overall running time low. Specifically,
91 * the parallelization parameter p is 1, the block size parameter r is 8, and the hashing output
92 * length is 32-byte.
Bo Zhue066a592018-03-19 22:32:27 -070093 */
Dmitry Dementyevfd4ae0b2018-03-23 11:06:24 -070094 public static @NonNull KeyDerivationParams createScryptParams(
Bo Zhu40d8a45b2018-03-21 20:07:43 -070095 @NonNull byte[] salt, int memoryDifficulty) {
96 return new KeyDerivationParams(ALGORITHM_SCRYPT, salt, memoryDifficulty);
Bo Zhue066a592018-03-19 22:32:27 -070097 }
98
99 /**
Dmitry Dementyevf8ae5de2018-01-08 18:08:23 -0800100 * @hide
101 */
Dmitry Dementyevfd4ae0b2018-03-23 11:06:24 -0700102 private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700103 this(algorithm, salt, /*memoryDifficulty=*/ -1);
Bo Zhue066a592018-03-19 22:32:27 -0700104 }
105
106 /**
107 * @hide
108 */
Dmitry Dementyev86f5bb12018-03-27 16:58:50 -0700109 private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt,
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700110 int memoryDifficulty) {
Robert Berry81ee34b2018-01-23 11:59:59 +0000111 mAlgorithm = algorithm;
112 mSalt = Preconditions.checkNotNull(salt);
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700113 mMemoryDifficulty = memoryDifficulty;
Robert Berry81ee34b2018-01-23 11:59:59 +0000114 }
115
116 /**
117 * Gets algorithm.
118 */
119 public @KeyDerivationAlgorithm int getAlgorithm() {
120 return mAlgorithm;
121 }
122
123 /**
124 * Gets salt.
125 */
126 public @NonNull byte[] getSalt() {
127 return mSalt;
128 }
129
Bo Zhue066a592018-03-19 22:32:27 -0700130 /**
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700131 * Gets the memory difficulty parameter for the hashing algorithm.
Bo Zhue066a592018-03-19 22:32:27 -0700132 *
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700133 * <p>The effect of this parameter depends on the algorithm in use. For example, please see
134 * {@link #createScryptParams(byte[], int)} for choosing the parameter for SCRYPT.
135 *
136 * <p>If the specific algorithm does not support such a memory difficulty parameter, its value
137 * should be -1.
Bo Zhue066a592018-03-19 22:32:27 -0700138 */
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700139 public int getMemoryDifficulty() {
140 return mMemoryDifficulty;
Bo Zhue066a592018-03-19 22:32:27 -0700141 }
142
Dmitry Dementyevebe53272019-03-05 13:33:24 -0800143 public static final @NonNull Parcelable.Creator<KeyDerivationParams> CREATOR =
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -0800144 new Parcelable.Creator<KeyDerivationParams>() {
Robert Berry81ee34b2018-01-23 11:59:59 +0000145 public KeyDerivationParams createFromParcel(Parcel in) {
146 return new KeyDerivationParams(in);
147 }
148
149 public KeyDerivationParams[] newArray(int length) {
150 return new KeyDerivationParams[length];
151 }
152 };
153
Robert Berry81ee34b2018-01-23 11:59:59 +0000154 @Override
155 public void writeToParcel(Parcel out, int flags) {
156 out.writeInt(mAlgorithm);
157 out.writeByteArray(mSalt);
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700158 out.writeInt(mMemoryDifficulty);
Robert Berry81ee34b2018-01-23 11:59:59 +0000159 }
160
161 /**
162 * @hide
163 */
164 protected KeyDerivationParams(Parcel in) {
165 mAlgorithm = in.readInt();
166 mSalt = in.createByteArray();
Bo Zhu40d8a45b2018-03-21 20:07:43 -0700167 mMemoryDifficulty = in.readInt();
Robert Berry81ee34b2018-01-23 11:59:59 +0000168 }
169
170 @Override
171 public int describeContents() {
172 return 0;
173 }
174}